// constants
const reminderFox_TOOLTIP_LINE_LENGTH = 100;
const reminderFox_TOOLTIP_WITH_TODOS_LINE_LENGTH = 65;
const reminderFox_ALERT_TEXT_MAX_LENGTH = 100;
const reminderFox_MONTHLY_WILDCARD = "*";

const reminderFox_HOUR_TIMEOUT = 1800000; // changed to half hour instead of 1 hour= 3600000  // dump: externalize this to a pref (read it first time only; then store it)
const reminderFox_ALARM_DELAY = 4000;  // make sure 500ms between each alarm, or mozilla creates a blank window

var reminderFox_alarmList = new Array();

var reminderFox_lastStatusBarClick;

 var reminderFox_initialized = false;
// Cache the last reminders
var reminderFox_lastDay = null;

var reminderFox_lastAlarmTime = null;


function rmFx_getWindow(aWin) {
	var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
	var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
	return windowManagerInterface.getMostRecentWindow(aWin);
}


// Launches the 'edit reminder' dialog, fills in Reminders list
function reminderFox_openAddRemindersDialog( closeIfOpen ) {
   var topWindow = rmFx_getWindow("window:reminderFoxEdit");
   if (topWindow) {
		var currentClickTime = new Date().getTime();
		if ( reminderFox_lastStatusBarClick != null &&  
			( (currentClickTime - reminderFox_lastStatusBarClick ) < 700 ) ) {
				closeIfOpen = false;
 		}
   		if ( closeIfOpen != null && closeIfOpen == true ) {
   			topWindow.close();
   		}
   		else {
	   		try { 
	    		 topWindow.focus();
	   		}
	   		catch ( e ) {   			
	   		}
   		}
   }
   else {
		var newOptions = { callback: reminderFox_networkSynchronizeCallback, clearMailLabelCallback: reminderFox_clearMailLabelCallback, processRemindersCallback: reminderFox_initializeReminderFoxHourly  };	    	  
		window.openDialog("chrome://reminderfox/content/addreminder-dialog.xul",
			"addreminder-dialog", "chrome,centerscreen,resizable,dialog=no", "reminders", newOptions);
	}	
	reminderFox_lastStatusBarClick = new Date().getTime();
}

function reminderFox_clearMailLabelCallback(messageID) {
	try {  // can't clear Label with non messenger !! 
		reminderFox_clearLabelByMessageID( messageID);
	} catch (ex) {}
}

function reminderFox_openOptionsDialog() {
   var topWindow = rmFx_getWindow("window:reminderFoxOptions");
  
   if (topWindow) {
   		try {
    		 topWindow.focus();
   		}
   		catch ( e ) {
   		}
   }
   else {
		window.openDialog('chrome://reminderFox/content/options/options.xul', 'reminderFox-options', 'chrome');
	}
}

function reminderFox_openQuickAlarmDialog() {
	window.openDialog('chrome://reminderFox/content/alarms/quickAlarmDialog.xul', 'quickAlarm', 'chrome,dialog=no');
}




// Launches the 'edit reminder' dialog, fills in Reminders list
function reminderFox_openAddTodosDialog(closeIfOpen) {
   var topWindow = rmFx_getWindow("window:reminderFoxEdit");
 
   if (topWindow) {
		var currentClickTime = new Date().getTime();
		if ( reminderFox_lastStatusBarClick != null &&  
			( (currentClickTime - reminderFox_lastStatusBarClick ) < 700 ) ) {
				closeIfOpen = false;
 		}
   		if ( closeIfOpen != null && closeIfOpen == true ) {
   			topWindow.close();
   		}
   		else {
	   		try { 
	    		 topWindow.focus();
	   		}
	   		catch ( e ) {   			
	   		}
   		}
   }
   else {
   	 var newOptions = { callback: reminderFox_networkSynchronizeCallback, clearMailLabelCallback: reminderFox_clearMailLabelCallback, processRemindersCallback: reminderFox_initializeReminderFoxHourly    };	 
	window.openDialog("chrome://reminderfox/content/addreminder-dialog.xul", 
		"addreminder-dialog", "chrome,centerscreen,resizable,dialog=no", "todos", newOptions);
	}
	
	reminderFox_lastStatusBarClick = new Date().getTime();
}

function reminderFox_openDoubleClickDialog(event) {
    if (event.button == 0) {
		var defaultEditType = REMINDER_FOX_DEFAULT_EDIT_DEFAULT;			
		try {
			defaultEditType = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_DEFAULT_EDIT);
		} catch(e) {
		}	
		if ( defaultEditType == "todos" )  {
			reminderFox_openAddTodosDialog(true);
		}
		else {
			reminderFox_openAddRemindersDialog(true);
		}
	}
}



function  reminderFox_processAlarm( recentReminderOrTodo, isReminder, listName ) { 
	var alarmInfo = null;
	var changed = false;
	var alarmTime = null;
	var lastSnoozeTime = null;
	
	var newDate = new Date( recentReminderOrTodo.date.getFullYear(), recentReminderOrTodo.date.getMonth(), recentReminderOrTodo.date.getDate(), 
		recentReminderOrTodo.date.getHours(), recentReminderOrTodo.date.getMinutes() );
	if ( recentReminderOrTodo.allDayEvent ) {
		newDate.setHours( 0, 0 );
	}
	var mins = 	newDate.getMinutes();
	var alarmMinutes = null;
	alarmMinutes = reminderFox_getAlarmInMinutes( recentReminderOrTodo.alarm );
	
	reminderFox_logMessageLevel("alarm: reminder date: " + newDate + "; alarmMinutes: " + alarmMinutes , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
	
	// dump: if a RUC=2 reminder, and no snooze...  maybe just always alarm?
	if ( alarmMinutes != null ) { 
		newDate.setMinutes( mins - alarmMinutes );
		alarmTime = newDate.getTime();	
		if ( recentReminderOrTodo.snoozeTime != null ) { // if this alarm has been snoozed, then get its snooze time		
			var snoozeAlarmTime = recentReminderOrTodo.snoozeTime;
			var index = snoozeAlarmTime.indexOf( ';' );	
			if ( index != -1 ) {
				lastSnoozeTime = snoozeAlarmTime.substring( index + 1);			
				snoozeAlarmTime = snoozeAlarmTime.substring( 0, index );				
				// separate out: -PT120M
				lastSnoozeTime = lastSnoozeTime.substring( 2, lastSnoozeTime.length-1);			
			}			
			//dump( "alarm: " + recentReminderOrTodo + ":" + snoozeAlarmTime + ": " + alarmTime );
			if ( snoozeAlarmTime > alarmTime ) {
				alarmTime = snoozeAlarmTime;
			}
			else {
				// this is an old snooze time...  older than the current alarm, so it will never execute.  Clear it.
				//changed = true;
				// update: actually this will fail, for repeating reminders as upcoming occurrences would cause this
				// conditional to be hit and incorrectly clear the snooze time
				//recentReminderOrTodo.snoozeTime = null;
			}
		}
	}
	else { // if the alarm can not be retrieved properly, return (unless a snooze time is available)		
		if ( recentReminderOrTodo.snoozeTime != null ) {
			var snoozeAlarmTime = recentReminderOrTodo.snoozeTime;
			var index = snoozeAlarmTime.indexOf( ';' );
			if ( index != -1 ) {
				lastSnoozeTime = snoozeAlarmTime.substring( index + 1);
				snoozeAlarmTime = snoozeAlarmTime.subSring( 0, index );
				// separate out: -PT120M
				lastSnoozeTime = lastSnoozeTime.substring( 2, lastSnoozeTime.length-1);				
			}	
			alarmTime = snoozeAlarmTime;
		}
		else {
			return changed;
		}
	}
		
	var currentTime = new Date().getTime();
	var missedAlarm = false;
	var timeDifference = alarmTime - currentTime;
	
	reminderFox_logMessageLevel("\n\n**************\nProcess Alarm: " + recentReminderOrTodo.date + "\n" + recentReminderOrTodo.summary +"\n" +  
		"alarmMinutes; " + alarmMinutes + " --- alarmTime: " + alarmTime + " == currentTime: " + currentTime + 
		"timeDiff: " + timeDifference + "\nlastAck: " + recentReminderOrTodo.alarmLastAcknowledge + "; Listname: " + listName , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
//	dump("\n\n**************\nProcess Alarm: " + recentReminderOrTodo.date + "\n" + recentReminderOrTodo.summary +"\n" +  
//		"alarmMinutes; " + alarmMinutes + " --- alarmTime: " + alarmTime + " == currentTime: " + currentTime + 
//		"timeDiff: " + timeDifference + "\nlastAck: " + recentReminderOrTodo.alarmLastAcknowledge + "; Listname: " + listName , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
	reminderFox_logMessageLevel("\n\n**************\nProcess Alarm: " + new Date() + " -- " + recentReminderOrTodo.date + "\n" + recentReminderOrTodo.summary +"\n" +  
		"alarmMinutes; " + alarmMinutes + " --- alarmTime: " + alarmTime + " == currentTime: " + currentTime + 
		"timeDiff: " + timeDifference + "\nlastAck: " + recentReminderOrTodo.alarmLastAcknowledge + "; Listname: " + listName , REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
	if ( timeDifference < 0 ) {
		// check acknowledge
		var ackDate = new Date();
		ackDate.setTime( recentReminderOrTodo.alarmLastAcknowledge );  // TODO check
		
		var d2 = new Date();
		var alarmD = new Date();
		alarmD.setTime(alarmTime);
		
		reminderFox_logMessageLevel( "ackdate: "  + recentReminderOrTodo.alarmLastAcknowledge + " less than: " + alarmTime , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
		reminderFox_logMessageLevel( "ackdate: "  + ackDate + " less than: " +alarmD , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO

		if ( recentReminderOrTodo.alarmLastAcknowledge != null  &&  // don't check alarms of old-style reminders (i.e. they have no ack)
			 recentReminderOrTodo.alarmLastAcknowledge < alarmTime ) {
			 // this past alarm was never acknowledged; let's do it now
			 timeDifference = 0;
			 missedAlarm = true;
			 
			 
		}
		reminderFox_logMessageLevel( "alarm:set missed: " + missedAlarm, REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
	}
	// allow for a minute time buffer
	if ( timeDifference < 0 && timeDifference >= -60000 ) {
		timeDifference = 0;
	}
	// check if the time difference occurs in the next 60 minutes
	var timeDifferenceInMinutes = 0;
	if ( timeDifference != 0 ) {
		timeDifferenceInMinutes = timeDifference/60000;
	}
	if ( timeDifferenceInMinutes >= 0 && timeDifferenceInMinutes  <= 60 ) {		
		var windowEnumerator =  reminderFox_getWindowEnumerator();
		if (windowEnumerator.hasMoreElements()) {
			var oldestWindow = windowEnumerator.getNext();
						 
			// check alarm list
			var alarmReminderId = recentReminderOrTodo.id;
			// if good - add to alarm list
			var found = false;
			for ( var i = 0; i < oldestWindow.reminderFox_alarmList.length && !found; i++ ) {
				var currentAlarmObject =  oldestWindow.reminderFox_alarmList[i];
				
				var currentAlarmId =currentAlarmObject .alarmId;
				if ( currentAlarmId== alarmReminderId ) {			
					// found an existing alarm set for this reminder...  
					
					
//					if ( currentAlarmObject.snoozed ) { 
//						// if it's been SNOOZED; then ignore as that snooze is going to go off no matter what
//						// update 10/03/2010 - disabling this; this was causing issues when there was an old snooze value,
//						// and a repeating daily reminder; the next day it would not alarm, because there was an old snooze value
//						//...  I believe this original logic is already handled; if the alarm is snoozed, it uses that as the snooze
//						// value.  If it's a repeating reminder, one alarm will be snoozed, and the next value will occur
//						found = true;
//						break;
//					}								
				
					var currentAlarmTime = currentAlarmObject.timeOfAlarm; 
					var alarmTimeDiff = alarmTime - currentAlarmTime;
					if ( (alarmTimeDiff < -60000 || alarmTimeDiff >  60000) && !missedAlarm) {
						// times are different; delete old and add new (only if this is not a missed alarm - b/c we'll just show the upcoming alarm instead)
						reminderFox_removeElement( oldestWindow.reminderFox_alarmList, i);
						reminderFox_logMessageLevel( "alarm: Remove alarm" , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
						//reminderFox_logMessageLevel( "alarm: Remove alarm1: " , REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
						break;
					}
					else {
						// times are close enough (within a minute); we don't need to add to the list
						found = true;
					}
				}
			}		
			reminderFox_logMessageLevel( "alarm:1 FOUND: " + found, REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
	
			if ( !found ) {
				// add him
				reminderFox_logMessageLevel( "alarm: Setting alarm: " +recentReminderOrTodo.summary, REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
	
				// if this was a snoozed alarm (in the ICS file) then mark him as snoozed
				var isSnoozed = false;
				if ( recentReminderOrTodo.snoozeTime != null ) {
					isSnoozed = true;					
				}
				//
				//reminderFox_logMessageLevel( "alarm: adding to list: " +recentReminderOrTodo.summary + "; alarmId: " + alarmReminderId + "; timeOfAlarm: " + alarmTime, REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
				//reminderFox_logMessageLevel( "alarm: adding to list:  len= " + oldestWindow.reminderFox_alarmList.length + "; " +recentReminderOrTodo.summary + "; alarmId: " + alarmReminderId + "; timeOfAlarm: " + alarmTime, REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
	
				
		 		oldestWindow.reminderFox_alarmList[oldestWindow.reminderFox_alarmList.length]  = 
					{ alarmId: alarmReminderId,  timeOfAlarm: alarmTime,  snoozed: isSnoozed };
					
				//reminderFox_logMessageLevel( "alarm: ADDED:  len= " + oldestWindow.reminderFox_alarmList.length + "; " +recentReminderOrTodo.summary + "; alarmId: " + alarmReminderId + "; timeOfAlarm: " + alarmTime, REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
	
				var missedAlarmString = "false";
				if ( missedAlarm  ) {  
					missedAlarmString = "true";
				}
				var isReminderString = "true";
				if ( !isReminder ) {
					isReminderString = "false";
				}
				if ( listName == null ){
					listName = "";
				}
				var isTodo = false;	
				if (isReminder != "true" && isReminder != true ) {
					isTodo = true;
				}		
				
				
				var newAlarm = { 
					alarmTabPanel: null,
					alarmRecentReminder: recentReminderOrTodo,
					alarmSnoozeTime: lastSnoozeTime,
					alarmListName: listName,
					alarmTimeString: alarmTime,
					alarmIsReminder: isReminderString,
					alarmIsTodo: isTodo,
					alarmAlarmMissed: missedAlarmString,
					synccallback: reminderFox_networkSynchronizeCallback,
					clearLabelCallback: reminderFox_clearMailLabelCallback,
					alarmCurrentAlarmId: alarmReminderId,
					reminderTime: recentReminderOrTodo.date.getTime(),
					reminderTimeDifference : timeDifference 
				};
						
						
				if ( timeDifference <= 0 || missedAlarm ) {
					// do nothing; will return missed alarm
					alarmInfo = newAlarm;
				
				}
				else {
					var alarmInfoArray = new Array();
					alarmInfoArray[0] = newAlarm;
						
					//alert( "A1!: " + alarmInfoArray[0].alarmRecentReminder.id  + " --> alarm in minutes :" + (timeDifference/60/ 1000) );
					oldestWindow.setTimeout(oldestWindow.reminderFox_showMissedAlarmsSnooze, 
						timeDifference,
						alarmInfoArray[0].alarmSnoozeTime, 
						alarmInfoArray[0].alarmRecentReminder.id,
						alarmInfoArray[0].alarmListName,
						alarmInfoArray[0].alarmTimeString ,
						alarmInfoArray[0].alarmIsReminder,
						alarmInfoArray[0].alarmIsTodo,
						alarmInfoArray[0].alarmAlarmMissed,
						alarmInfoArray[0].reminderTime,
						alarmInfoArray[0].reminderTimeDifference );
						
						
				}
			}
		}
	}
	
	return alarmInfo;
}


function reminderFox_showMissedAlarmsSnooze( alarmSnoozeTime, alarmRecentReminderID, alarmListName, 
	alarmTimeString, alarmIsReminder, alarmIsTodo, alarmAlarmMissed, reminderTime, 
	reminderTimeDifference ) { 
	
//	alert( "INSIDE HERE: " + alarmSnoozeTime + ", " +  alarmRecentReminderID+ ", " +  alarmListName+ ", " + 
//	alarmTimeString+ ", alarmisreminder: " + alarmIsReminder+ ", " + alarmIsTodo+ ", " + alarmAlarmMissed+ ", " +  reminderTime+ ", " +  
//	reminderTimeDifference );
	
	var isReminder = false;
	if ( alarmIsReminder == 1  || alarmIsReminder == true || alarmIsReminder == "true") {
		isReminder = true;
	}
	
	var isTodo = false;
	if ( alarmIsTodo == 1  || alarmIsTodo == true || alarmIsTodo == "true") {
		isTodo = true;
	}
	
	var reminderOrTodo = null;
	if ( isReminder == "true" || isReminder == true ) {
		reminderOrTodo =	reminderFox_getRemindersById( alarmRecentReminderID);
	//	alert( "FOUND IT: " + reminderOrTodo );
	}
	else {
		reminderOrTodo =	reminderFox_getSpecificTodoById( alarmRecentReminderID);
	}
	
	var alarmMissed = false;
	if ( alarmAlarmMissed == 1 ) {
		alarmMissed = true;
	}
	
	var newAlarm = { 
		quickAlarmText : null,
		alarmTabPanel: null,
		alarmRecentReminder: reminderOrTodo,
		alarmSnoozeTime: alarmSnoozeTime,
		alarmListName: alarmListName,
		alarmTimeString: alarmTimeString,
		alarmIsReminder: isReminder,
		alarmIsTodo: isTodo,
		alarmAlarmMissed: alarmMissed,
		synccallback: reminderFox_networkSynchronizeCallback,
		clearLabelCallback: reminderFox_clearMailLabelCallback,
		alarmCurrentAlarmId: alarmRecentReminderID,
		reminderTime: reminderTime,
		reminderTimeDifference : reminderTimeDifference 
	};
	
	 var alarmInfos = new Array();
	 alarmInfos[0] = newAlarm;
	 
	// alert( "JSON: " + JSON.stringify(alarmInfos) );
	 reminderFox_showMissedAlarms( alarmInfos );
}


function reminderFox_showMissedAlarmsSnooze2( alarmSnoozeTime, alarmRecentReminderID, alarmListName, 
	alarmTimeString, alarmIsReminder, alarmIsTodo, alarmAlarmMissed, reminderTime, 
	reminderTimeDifference ) { 
	
	var reminderOrTodo = null;
	var isReminder = false;
	if ( alarmIsReminder == 1 ) {
		isReminder = true;
	}
	
	var isTodo = false;
	if ( alarmIsTodo == 1 ) {
		isTodo = true;
	}
		
	
	if ( isReminder == "true" || isReminder == true ) {
		reminderOrTodo =	reminderFox_getRemindersById( alarmRecentReminderID);
	}
	else {
		reminderOrTodo =	reminderFox_getSpecificTodoById( alarmRecentReminderID);
	}
		
	var alarmMissed = false;
	if ( alarmAlarmMissed == 1 ) {
		alarmMissed = true;
	}
	
	var newAlarm = { 
		quickAlarmText : null,
		alarmTabPanel: null,
		alarmRecentReminder: reminderOrTodo,
		alarmSnoozeTime: alarmSnoozeTime,
		alarmListName: alarmListName,
		alarmTimeString: alarmTimeString,
		alarmIsReminder: isReminder,
		alarmIsTodo: isTodo,
		alarmAlarmMissed: alarmMissed,
		synccallback: reminderFox_networkSynchronizeCallback,
		clearLabelCallback: reminderFox_clearMailLabelCallback,
		alarmCurrentAlarmId: alarmRecentReminderID,
		reminderTime: reminderTime,
		reminderTimeDifference : reminderTimeDifference 
	};
	 var alarmInfos = new Array();
	 alarmInfos[0] = newAlarm;
	reminderFox_openAlarmWindow(alarmInfos);
}





function reminderFox_showMissedAlarms( alarmInfos ) {  
	var alarmArray = new Array();
	for (var k = 0; k < alarmInfos.length; k++) {
		var alarmInfo = alarmInfos[k];
		
		if ( alarmInfo.quickAlarmText != null ) { // a quick alarm
			alarmArray[alarmArray.length] = alarmInfo;
			continue;
		}
		
		var reminderdateTime = alarmInfo.reminderTime;
		var alarmReminderId = alarmInfo.alarmCurrentAlarmId;
		var isReminder = alarmInfo.alarmIsReminder;
		var alarmTime = alarmInfo.alarmTimeString;
		var missedAlarm = alarmInfo.alarmAlarmMissed;
		
		// only show alarm if reminder still exists and it has not been marked complete
		//  (the user could have deleted/completed it since last setting the alarm timeout)
		var reminderOrTodo = alarmInfo.alarmRecentReminder;
		if (isReminder == "true" || isReminder == true ) {
			reminderOrTodo = reminderFox_getRemindersById(alarmReminderId);
		}
		else {
			reminderOrTodo = reminderFox_getSpecificTodoById(alarmReminderId);
		}
	
		if (reminderOrTodo != null) {
			var completed = false;
			if (isReminder == "true" || isReminder == true) {
				reminderOrTodo = reminderFox_cloneReminderFoxEvent(reminderOrTodo);
				reminderOrTodo.date.setTime(reminderdateTime);
				completed = reminderFox_isCompletedForDate(reminderOrTodo, reminderOrTodo.date);
			}
			else {
				reminderOrTodo = reminderFox_cloneReminderFoxTodo(reminderOrTodo);
				reminderOrTodo.date.setTime(reminderdateTime);
				completed = reminderFox_isCompletedForDate(reminderOrTodo, reminderOrTodo.date);
			}
			if (!completed) {
				// only show this reminder if it has not already been acknowledged
				var resultbool = (reminderOrTodo.alarmLastAcknowledge <= alarmTime);
				reminderFox_logMessageLevel("alarm: last acknowlege: " + reminderOrTodo.alarmLastAcknowledge + " <=? " + alarmTime + " ; result = " + (reminderOrTodo.alarmLastAcknowledge <= alarmTime), REMINDER_FOX_LOG_LEVEL_SUPER_FINE); //TODO
				if (reminderOrTodo.alarmLastAcknowledge == null || reminderOrTodo.alarmLastAcknowledge <= alarmTime) {
					var windowEnumerator = reminderFox_getWindowEnumerator();
					if (windowEnumerator.hasMoreElements()) {
						var oldestWindow = windowEnumerator.getNext();
						for (var i = 0; i < oldestWindow.reminderFox_alarmList.length; i++) {
							var currentAlarmId = oldestWindow.reminderFox_alarmList[i].alarmId;
							var snooze = false;
							if (currentAlarmId == alarmReminderId) {
								if (oldestWindow.reminderFox_alarmList[i].snoozed) {
									snooze = true;
								}
								var currentAlarmTime;
								if (snooze) {
									var alarmTimeInt = parseInt(alarmTime);
									var actualCurrentTime = new Date().getTime();
									
									// if you snooze an alarm for a long value (like 28 days), mozilla calls the setTimeout immediately.  We need
									// to check against that (they probably have some bug when an int value gets too big)
									actualCurrentTime = actualCurrentTime + 2000; // add 2 seconds for a small buffer
									var diffcheck = actualCurrentTime < alarmTimeInt;
									if (actualCurrentTime < alarmTimeInt) {
										reminderFox_logMessageLevel("alarm: current time is less than alarm time; not showing alarm.  Current time " + (actualCurrentTime - 2000) + "; alarm time set for: " + alarmTimeInt, REMINDER_FOX_LOG_LEVEL_SUPER_FINE); //TODO
										continue;
									}
									
									
									currentAlarmTime = parseInt(alarmTime);
								}
								else {
									currentAlarmTime = oldestWindow.reminderFox_alarmList[i].timeOfAlarm;
								}
								
								var alarmTimeDiff = alarmTime - currentAlarmTime;
								
								reminderFox_logMessageLevel("alarm: original alarm time: " + alarmTime + "; current alarm time: " + currentAlarmTime + ";  alarmTimeDiff: " + alarmTimeDiff, REMINDER_FOX_LOG_LEVEL_SUPER_FINE); //TODO
								// ensure that the current stored alarm time is the same as the alarm time this function was called with.  
								// This check is in case the user changed the alarm time after the first timeout had been issued.  You only 
								// want to show one alert at the last time the user selected
								if (alarmTimeDiff >= -60000 && alarmTimeDiff <= 60000) {

									if (!snooze && missedAlarm == "false") { // don't check, if this is a past alarm (times won't match because it was set to go off not at current time, but a previous time)							
										// secondary check - in case of FireFox setTimeout Bug;		
										// check if the current time is about  when the alarm was set for
										var currentSystemTime = new Date().getTime();
										var alarmSystemTimeDiff = alarmTime - currentSystemTime;
										if (alarmSystemTimeDiff < -60000 || alarmSystemTimeDiff > 60000) {
											reminderFox_logMessageLevel("alarm: system time diff failed check; returning: " + alarmSystemTimeDiff, REMINDER_FOX_LOG_LEVEL_SUPER_FINE); //TODO
											continue;
										}
									}
									
								// Mozilla bug: it seems that if you open two alarm dialog windows at the same time, only one of the loadAlarm() functions gets called 
								// from the new window.  So we introduce a small second delay between opening each alarm - so if you have several alarms set to go off
								// at the same time, you will always see them properly and not get a blank window in one of them
								var time = new Date().getTime(); 		
								reminderFox_logMessageLevel( "alarm: time: " + time + "; lastalarmtime" +reminderFox_lastAlarmTime + " ; " +  reminderFox_ALARM_DELAY    , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
								alarmInfo.alarmRecentReminder = reminderOrTodo;				
								if ( alarmInfos.length > 1 ||  // if there's multiple reminders; continue in here.  Only if there is 1 reminder would we want to set the delay
									(reminderFox_lastAlarmTime == null || (  time > (reminderFox_lastAlarmTime + reminderFox_ALARM_DELAY) ) ) ) {
										reminderFox_lastAlarmTime = time;
										reminderFox_logMessageLevel( "alarm: opening alarm dialog: " + reminderOrTodo.summary   , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
										alarmArray[alarmArray.length] = alarmInfo;
									}
									else {
										reminderFox_logMessageLevel( "alarm: Setting time out..."   , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO																				
											
										//alert( "A2!" );	
										oldestWindow.setTimeout(oldestWindow.reminderFox_showMissedAlarmsSnooze2, 
											reminderFox_ALARM_DELAY,
											alarmInfo.alarmSnoozeTime, 
											alarmInfo.alarmRecentReminder.id,
											alarmInfo.alarmListName,
											alarmInfo.alarmTimeString ,
											alarmInfo.alarmIsReminder,
											alarmInfo.alarmIsTodo,
											alarmInfo.alarmAlarmMissed,
											alarmInfo.reminderTime,
											alarmInfo.reminderTimeDifference );																		
									}
										
									break;
								}
							}
						}
					}
				}
				else {
				}
			}
		}
	}
	//alert( "IN ARRAY: " + alarmArray[0].alarmRecentReminder.summary + " :" + alarmArray[0].alarmRecentReminder.originalDate);
	reminderFox_openAlarmWindow( alarmArray, true );
			
}

function reminderFox_openAlarmWindow(alarmArray, ignoreCheck) {
	var showAlarmsInTabs= reminderFox_getPreferenceValue( REMINDER_FOX_ALARMS_SHOW_IN_TABS );
	
	// go through all options
	if ( alarmArray != null && alarmArray.length > 0 ) {
	   var topWindow = rmFx_getWindow("window:reminderFoxAlarmDialog");
	   
		var time = new Date().getTime(); 		
		
		if ( alarmArray.length == 1 && alarmArray[0].quickAlarmText != null ) {
			var q_alarm = reminderFox_getQuickAlarm( alarmArray[0].quickAlarmText );
			//alert( "doing quick alarm check: " + q_alarm.text + "; time = " + time + " ; quick alarm time: " + q_alarm.alarmTime ); dump: remove  dump(): nls
			
			if ( q_alarm != null && ( (time  + 10000) <   q_alarm.alarmTime ) ) {
				// check if it's snooze time has yet occurred;
				// there is a bug where sometimes snoozing a reminder will automatically call the 
				// setTimeout function and come back in here;  if we check the snooze time and it 
				// is in the future (+/- 2 seconds or so) then just ignore it
				
				// let's set a new timeout and try again
				var windowEnumerator =  reminderFox_getWindowEnumerator();
				if (windowEnumerator.hasMoreElements()) {
					var oldestWindow = windowEnumerator.getNext();	
					// alert( "A3! quick alarm: " +  alarmArray[0].quickAlarmText + " --- "  + (q_alarm.alarmTime + 2000)  + " -- " + (q_alarm.alarmTime - time) + " -- " + (q_alarm.alarmTime - time + 2000 ));
					  
					// if snooze greater than an hour; just let hourly process do it
					if ( ((q_alarm.alarmTime - time) + 2000)  > 3600000 ) {
					 	return;
					}
						  					  
					oldestWindow.setTimeout(oldestWindow.reminderFox_showQuickAlarm, 
												(q_alarm.alarmTime - time) + 2000,
												alarmArray[0].quickAlarmText,
												alarmArray[0].alarmSnoozeTime );
			
					return;
				}
			}
		}
							
		reminderFox_logMessageLevel( "alarm2: ignoreCheck = " + ignoreCheck + "; time: " + time + "; lastalarmtime" +reminderFox_lastAlarmTime + " ; " 
			+  reminderFox_ALARM_DELAY + "; alarmArray.length = " + alarmArray.length + 
			"(  time > (reminderFox_lastAlarmTime + reminderFox_ALARM_DELAY) ) = " + 
			(  time > (reminderFox_lastAlarmTime + reminderFox_ALARM_DELAY) )    , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
			
				reminderFox_logMessageLevel(new Date()  + "alarm2: ignoreCheck = " + ignoreCheck + "; time: " + time + "; lastalarmtime" +reminderFox_lastAlarmTime + " ; " 
			+  reminderFox_ALARM_DELAY + "; alarmArray.length = " + alarmArray.length + 
			"(  time > (reminderFox_lastAlarmTime + reminderFox_ALARM_DELAY) ) = " + 
			(  time > (reminderFox_lastAlarmTime + reminderFox_ALARM_DELAY) )   , REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
			
		if ( ignoreCheck || alarmArray.length > 1 ||  // if there's multiple reminders; continue in here.  Only if there is 1 reminder would we want to set the delay
			(reminderFox_lastAlarmTime == null || (  time > (reminderFox_lastAlarmTime + reminderFox_ALARM_DELAY) ) ) ) {
			reminderFox_lastAlarmTime = time;
			if (showAlarmsInTabs && topWindow) {				 						
		 	  try { 
					// close and reopen
					var selectedIndex = topWindow.getRF_alarmIndex();
					var existingAlarmArray = topWindow.getRF_AlarmArray();
					// see if this quick alarm is already being shown...
					for ( var j = alarmArray.length-1; j >= 0; j-- ) {
						if ( alarmArray[j].quickAlarmText != null ) {
							for ( var k = 0; k < existingAlarmArray.length; k++ ) {
								if ( existingAlarmArray[k].quickAlarmText != null &&
									existingAlarmArray[k].quickAlarmText == alarmArray[j].quickAlarmText ) {
									// alarm already exists; remove from current list
									reminderFox_removeElement(alarmArray, j);
									break;
								}
							}
						}
						// see if this alarm is already being shown
						else if ( alarmArray[j].alarmRecentReminder != null ) {
							for ( var k = 0; k < existingAlarmArray.length; k++ ) {
								if ( existingAlarmArray[k].alarmRecentReminder != null &&
									existingAlarmArray[k].alarmRecentReminder.id == alarmArray[j].alarmRecentReminder.id ) {
									// alarm already exists; remove from current list
									
									// if this is a single repeating alarm that is going off, we want to alarm 
									// with the latest version  
									// (example: a daily "Take Pill" reminder - you want the alarm to go off every
									// day (re-sound the alarm), even if that reminder is already in the list
									if (ignoreCheck && alarmArray.length == 1) {
										// remove from old list
										reminderFox_removeElement(existingAlarmArray, k);
									}
									else {									
										reminderFox_removeElement(alarmArray, j);
									}
									// see if the alarm is an old version...  if this is new alarm, let's reshow it
									break;
								}
								// dump() could add a check for alarm ack here?  need to know the current alarm time and last ack?
								
							}
						}
					}
					if ( alarmArray.length > 0 ) {
						// close/reopen
						topWindow.reminderFox_reopeningWindow = true;
						topWindow.close();
						for ( var j = 0; j < alarmArray.length; j++ ) {
							existingAlarmArray[existingAlarmArray.length] = alarmArray[j]; 
						}
						
						//alert( "ORIG1" + existingAlarmArray[0].alarmRecentReminder.originalDate + "; " +  existingAlarmArray[0].alarmRecentReminder.summary + " - " + existingAlarmArray[0].alarmRecentReminder.date );
						
						var newOptions = {  alarmInfos: existingAlarmArray, showMissedAlarmsSnoozeCallback : reminderFox_showMissedAlarms}
						window.openDialog("chrome://reminderfox/content/alarms/alarmDialog.xul",
							"alarmOptionsDialog", "chrome,resizable,dialog=no", newOptions);
					    topWindow = rmFx_getWindow("window:reminderFoxAlarmDialog");
						if ( topWindow != null ) {
							topWindow.focus();
						}
					}
				   }
				   catch ( e ) {   			
				   }
				 }
				 else {
					if ( !showAlarmsInTabs ) {
						// go through all alarms and open in separate windows
						for ( var i = 0; i < alarmArray.length; i++ ) {
							var singleArray = new Array();
							singleArray[0] = alarmArray[i];
												//	alert( "ORIG2" + singleArray[0].alarmRecentReminder.originalDate + "; " +singleArray[0].alarmRecentReminder.summary + " - " + singleArray[0].alarmRecentReminder.date );
							
							var newOptions = {  alarmInfos: singleArray, showMissedAlarmsSnoozeCallback : reminderFox_showMissedAlarmsSnooze}
							window.openDialog("chrome://reminderfox/content/alarms/alarmDialog.xul",
								"alarmOptionsDialog"+new Date().getTime() + i, "chrome,resizable,dialog=no", newOptions);
							topWindow = rmFx_getWindow("window:reminderFoxAlarmDialog");
							if ( topWindow != null ) {
								topWindow.focus();
							}
						}
					}
					else {   
						
						var newOptions = {  alarmInfos: alarmArray, showMissedAlarmsSnoozeCallback : reminderFox_showMissedAlarmsSnooze}
						//we don't use alarmOptionsDialog + date =- sometimes showing a separate window
						window.openDialog("chrome://reminderfox/content/alarms/alarmDialog.xul",
							"alarmOptionsDialog", "chrome,resizable,dialog=no", newOptions);
						topWindow = rmFx_getWindow("window:reminderFoxAlarmDialog");
						if ( topWindow != null ) {
							topWindow.focus();
						}
					}
				}
			}
			else {
				var windowEnumerator =  reminderFox_getWindowEnumerator();
				if (windowEnumerator.hasMoreElements()) {
					var oldestWindow = windowEnumerator.getNext();	
					// sometimes called when 2 alarms are snoozed for same time immediately	
					
					var alarmInfo = alarmArray[0];
					//reminderFox_logMessageLevel( "alarm: Setting time out..." + alarmInfo.quickAlarmText   , REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
					if ( alarmInfo.quickAlarmText != null ) {
						
						// debug:
						//var q_alarm = reminderFox_getQuickAlarm( alarmArray[0].quickAlarmText );
						//alert( "doing quick alarm check: " + q_alarm.text + "; time = " + time + " ; quick alarm time: " + q_alarm.alarmTime ); dump: remove  dump(): nls

						var text = alarmInfo.quickAlarmText;
						var sTime = alarmInfo.alarmSnoozeTime;
						oldestWindow.setTimeout(function() { oldestWindow.reminderFox_showQuickAlarm(text,sTime) } , reminderFox_ALARM_DELAY);
					}
					else {
				
						/// dump:  - maybe here we should do a re-processing...

						//
						var st = alarmInfo.alarmSnoozeTime;
						var id1 = alarmInfo.alarmCurrentAlarmId;	
						
						// dump test this
						//var nuller = null; 
						//if ( alarmInfo.alarmCurrentAlarmId != null ) 
						//nuller = alarmInfo.alarmCurrentAlarmId;						
						//alert( "A4!" + alarmInfo.alarmSnoozeTime + " -- " +alarmInfo.alarmCurrentAlarmId + " __ " + nuller );
						//
						
											
						oldestWindow.setTimeout(oldestWindow.reminderFox_showMissedAlarmsSnooze2, 
							reminderFox_ALARM_DELAY,
							st, 
							id1,
							alarmInfo.alarmListName,
							alarmInfo.alarmTimeString ,
							alarmInfo.alarmIsReminder,
							alarmInfo.alarmIsTodo,
							alarmInfo.alarmAlarmMissed,
							alarmInfo.reminderTime,
							alarmInfo.reminderTimeDifference );
						}
						
					}
			}
				
		}
				
}


function reminderFox_showQuickAlarm( lastAlarmText, lastSnoozeTime, lastQuickAlarmNotes) {
	reminderFox_logMessageLevel( new Date()  + "INSIDE SHOW QUICKALARM: " + lastAlarmText + " - " +  lastSnoozeTime + " - "  + lastQuickAlarmNotes , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO

	// make sure quick alarm still exists and wasn't removed
	var q_alarm = reminderFox_getQuickAlarm( lastAlarmText );
	if ( q_alarm != null ) {
		var newAlarm = { 
			quickAlarmText : lastAlarmText,
			quickAlarmNotes : lastQuickAlarmNotes,
			alarmTabPanel: null,
			alarmRecentReminder: null,
			alarmSnoozeTime: lastSnoozeTime,
			alarmListName: null,
			alarmTimeString: null,
			alarmIsReminder: false,
			alarmIsTodo: false,
			alarmAlarmMissed: false,
			synccallback: reminderFox_networkSynchronizeCallback,
			clearLabelCallback: reminderFox_clearMailLabelCallback,
			alarmCurrentAlarmId: null,
			reminderTime: null,
			reminderTimeDifference : null 
		};
			
		var alarmArray = new Array();
		alarmArray[0]= newAlarm;
		reminderFox_openAlarmWindow(alarmArray);
	}
	else {
		reminderFox_logMessageLevel( new Date()  + "INSIDE ShowQuickAlarm: Removed" , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  
	}
}

// Launches the 'edit reminder' dialog, fills in Reminders list
function reminderFox_openAboutReminderFoxDialog() {
	window.openDialog("chrome://reminderfox/content/about.xul", "about", "chrome,centerscreen");
}


function reminderFox_processRecentReminders(processQuickAlarms){ 
	var changed = false;
	var alarmInfos = new Array();
	var NUM_OF_PAST_DAYS_TO_PROCESS = 90; // needs to be less than weekly reminder so Completed mark isn't cleared...  
	// the real fix is to check if the reminder you are clearing occurs today as well; if so don't clear the mark
	// Update 11/24/09: I don't think this is true anymore; we don't clear completed mark - we set last completed date; 
	// changing to look in the past 90(?) days for alarms, RUC, etc; that should be long enough
	var NUM_OF_DAYS_AHEAD_FOR_ALARM = 15; // let's look a couple weeks ahead in case an alarm is set to go off
	var i, j;
	
	var alarmsEnabled = true;
	var alertType;
	try {
		alertType = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ENABLE_ALERT_PREF);
	} 
	catch (e) {
		alertType = REMINDER_FOX_ENABLE_ALERT_PREF_ALL;
	}
	if (alertType.indexOf(REMINDER_FOX_SUSPEND_ALERT_PREF) != -1) {
		alarmsEnabled = false;
	}
	
	
	var reminderEvents = reminderFox_getReminderEvents(); 
	var reminder;
	
	// set dates to search during the last week only
	var todaysDate = new Date();
	var startDate = new Date();
	var endDateAlarmCheck = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
	endDateAlarmCheck.setDate(startDate.getDate() + NUM_OF_DAYS_AHEAD_FOR_ALARM);
	startDate.setDate(startDate.getDate() - NUM_OF_PAST_DAYS_TO_PROCESS);
	for (i = 0; i < reminderEvents.length; i++) {
		reminder = reminderEvents[i];
		
		// pass in false to not limit repeating instances returned; otherwise, 
		// we only get first 8 weekly/daily instances - this causes an issue if we are looking back
		// 3 months behind; we would not get the current instances for alarms, etc
		var allReminders = reminderFox_getAllRemindersInDateRange(reminder, startDate, endDateAlarmCheck, false);  
		if (allReminders.length == 0) {
			var dateCompare = reminderFox_compareDates(reminder.date, todaysDate);
			if (reminder.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED && dateCompare == -1) {
				allReminders = new Array();
				allReminders[0] = reminder;
			}
		}
		
		
		for (j = 0; j < allReminders.length; j++) {
			var recentReminder = allReminders[j];
			var dateCompare = reminderFox_compareDates(recentReminder.date, todaysDate);
			// if a reminder is set to Remind Until Complete (and it's already happened) set to today's date to check for alarm		
			if (recentReminder.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED && dateCompare == -1) {
				recentReminder = reminderFox_cloneReminderFoxEvent(recentReminder);
				recentReminder.originalDate = recentReminder.date;
				recentReminder.date = new Date(todaysDate.getFullYear(), todaysDate.getMonth(), todaysDate.getDate(), recentReminder.date.getHours(), recentReminder.date.getMinutes());
				//alert( "SETTING ORIG DATE:" + recentReminder.originalDate );
				dateCompare = 0; // set as today's date	
			}
			
			reminderFox_logMessageLevel("alarm: recent alarm" + j + ": " + recentReminder.summary + " -- " + recentReminder.alarm + " -- " + alarmsEnabled, REMINDER_FOX_LOG_LEVEL_SUPER_FINE); //TODO
			// check the alert for future and past reminders (for missed alerts)
			if (recentReminder.alarm != null && alarmsEnabled && !reminderFox_isCompletedForDate(recentReminder, recentReminder.date)) {
				var missedAlarmInfo = reminderFox_processAlarm(recentReminder, true, null);  // soo here we might have an old one 
				// showing in alarm, and then set a new one to go off the next hour...  how do I stop that?
				// when showing alarms, need to check existing list if it's the same reminder ID?  and don't show new one?
				// or remove old one...
				if (missedAlarmInfo != null) {
					missedAlarmInfo.originalDate = recentReminder.originalDate;
					alarmInfos[alarmInfos.length] = missedAlarmInfo;  
				}
			}
			
			// if the reminder happened in the past, we want to see if it should be move to RemindUntilComplete
			if (dateCompare == -1) {
				// check for any RemindUntilComplete - if found, set it to be shown in today's list of reminders
				if (recentReminder.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_TO_BE_MARKED) {
					if (reminder.recurrence.type == REMINDER_RECURRENCE_ONETIME || recentReminder.lastModified != null) {
						var modifiedDate = reminderFox_getStringAsDate(recentReminder.lastModified);
						// if you last modified this on or  before the reminder date, then set it as RUC;
						// otherwise if you've modified this after the reminder date (such as setting it complete)
						// then leave it alone and don't set it as RUC (unless it's a one-timer... then we'll just move it to RUC
						// since that is probably what they intended)
						if (reminder.recurrence.type == REMINDER_RECURRENCE_ONETIME ||
						(reminderFox_compareDates(modifiedDate, recentReminder.date) != 1 &&
						!reminderFox_isCompletedForDate(recentReminder, recentReminder.date))) { // don't change if it's Complete
							reminder.remindUntilCompleted = REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED;
							changed = true;
							reminder.lastModified = reminderFox_getDateAsString(todaysDate);
						}
					}
					else {
						reminder.remindUntilCompleted = REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED;
						changed = true;
						reminder.lastModified = reminderFox_getDateAsString(todaysDate);
					}
				}
			}
		}
	}
	
	
	// now process todos
	var allTodosHash = reminderFox_getAllTodosInDateRange(startDate, endDateAlarmCheck);
	for (var n in allTodosHash) {
		var allTodos = allTodosHash[n];
		for (i = 0; i < allTodos.length; i++) {
			var todo = allTodos[i];
			// check the alert for future and past reminders (for missed alerts)
			if (todo.alarm != null && alarmsEnabled && !reminderFox_isCompletedForDate(todo, todo.date)) {  
				//				var snoozeCleared = reminderFox_processAlarm( todo, false, n);
				//				if ( snoozeCleared ) {
				//					changed = true;
				//				}
				var missedAlarmInfo = reminderFox_processAlarm(todo, false, n);
				if (missedAlarmInfo != null) {
					alarmInfos[alarmInfos.length] = missedAlarmInfo;
				}
			}
			
		}
	}
	if ( processQuickAlarms ) {
		var quickAlarmArray = reminderFox_processQuickAlarms(true);
		for ( var q = 0; q < quickAlarmArray.length; q++ ) {
			alarmInfos[alarmInfos.length] = quickAlarmArray[q];
		}
	}
	
	// for any alarms:
	if (alarmInfos != null && alarmInfos.length > 0) {
		reminderFox_showMissedAlarms(alarmInfos);
	}
	
	return changed;
}
	
	




function reminderFox_createToolTip(todayRemindersArr, upcomingRemindersArr) {
	var j;
	var currentNode;
	var todayDescription;
	var upcomingDescription;
	var spacer;
	var todoDescription;
	
	var hideGayPaw = reminderFox_getPreferenceValue( REMINDER_FOX_HIDE_FOX_PAW );
	if ( hideGayPaw ) {
		document.getElementById('foxpaw').setAttribute("hidden", "true");	
	}
	
	// we'll set the icon depending on if there's current, upcoming, 
	// or no reminders
 	var icon = document.getElementById('reminderFox-statusLabel');
 	icon.setAttribute("status", "noReminders");

 	var todosArr = reminderFox_getVisibleTodos();
 		
 	// clear old tooltips
	var todayBox = document.getElementById("todaysRemindersBox");
	if ( todayBox != null ) {
	     while (todayBox.hasChildNodes()) {
	    	 todayBox.removeChild(todayBox.firstChild);
	  	 }		
	}
					
	var upcomingBox = document.getElementById("upcomingRemindersBox");
	if ( upcomingBox != null ) {
	     while (upcomingBox.hasChildNodes()) {
	    	 upcomingBox.removeChild(upcomingBox.firstChild);
	  	 }		
	}
	
	var todoBox = document.getElementById("todosBox");
	if ( todoBox != null ) {
	     while (todoBox.hasChildNodes()) {
	    	 todoBox.removeChild(todoBox.firstChild);
	  	 }	
	}
		
		
	// remove old tooltip box
	var tooltipChildren = document.getElementById("todosTooltip");		
	if ( tooltipChildren != null ) {
	    while (tooltipChildren.hasChildNodes()) {
		     tooltipChildren.removeChild(tooltipChildren.firstChild);
		}		
	}
	
	// remove old reminders box
	var tooltipChildrenReminders = document.getElementById("tooltipChildrenReminders");
	if ( tooltipChildrenReminders != null ) {
	    while (tooltipChildrenReminders.hasChildNodes()) {
		     tooltipChildrenReminders.removeChild(tooltipChildrenReminders.firstChild);
		}		
	}
	
	var showReminders = true;			
	try {
		showReminders = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_SHOW_REMINDERS_IN_TOOLTIP);
	} catch(e) {
	}			

	var showTooltips = true;			
	try {
		showTooltips = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_SHOW_TODOS_IN_TOOLTIP);
	} catch(e) {
	}			
 	
 	var tooltipWrapLength;

 	if ( todosArr != null && showReminders && showTooltips) {
 		tooltipWrapLength = reminderFox_TOOLTIP_WITH_TODOS_LINE_LENGTH;
 	}
 	else {
 		tooltipWrapLength = reminderFox_TOOLTIP_LINE_LENGTH;
 	}

 	if ( showReminders ) { 
 			todayDescription = document.createElement("description");
			todayDescription.setAttribute("id", "todayRemindersDescription");
			todayDescription.setAttribute("value",reminderFox_getBundle().getString("rf.main.tooltip.todaysReminders.title"));
			todayDescription.setAttribute("style", "font-weight:bold;");
			tooltipChildrenReminders.appendChild(todayDescription);
	
			var todayVbox = document.createElement("vbox");
			todayVbox.setAttribute("id", "todaysRemindersBox");
			tooltipChildrenReminders.appendChild(todayVbox);
 				
			spacer =  	document.createElement("spacer");	
 			spacer.setAttribute("id", "reminderSpacer");		
 			spacer.setAttribute("height", "4px");		
			tooltipChildrenReminders.appendChild(spacer); 			
 		
 	 		upcomingDescription = document.createElement("description");
			upcomingDescription.setAttribute("id", "upcomingRemindersDescription");
			upcomingDescription.setAttribute("value", reminderFox_getBundle().getString("rf.main.tooltip.upcomingReminders.title"));
			upcomingDescription.setAttribute("style", "font-weight:bold;");
			tooltipChildrenReminders.appendChild(upcomingDescription);

			var upcomingVbox = document.createElement("vbox");
			upcomingVbox.setAttribute("id", "upcomingRemindersBox");
			tooltipChildrenReminders.appendChild(upcomingVbox);

	 		reminderFox_populateTodayToolTip(todayRemindersArr, tooltipWrapLength );
	 		reminderFox_populateUpcomingToolTip(upcomingRemindersArr, tooltipWrapLength);
	}
	
	
	
	
	if ( showTooltips && todosArr != null ) {		
	 	// make sure ToDo's are at the start of the list	 	
		var todos = todosArr[REMINDER_FOX_DEFAULT_TODOS_CATEGORY];
		if ( todos != null && todos.length > 0) {		 
			reminderFox_populateTodoToolTip(todos, (tooltipWrapLength - 13), reminderFox_getBundle().getString( "rf.main.tooltip.todos.title" ) );	
		}
		
		// iterate over all of the ToDo lists in the order that the user defined in the preferences
	 	var todoLists = reminderFox_getPreferenceValue( REMINDER_FOX_TODO_LISTS );
	 	if ( todoLists != null && todoLists.length > 0) { 	
	 		var subscriptions = reminderFox_getSubscriptions();		
	 		var todoListsArray = todoLists.split(",");
	 		for ( var j = 0; j < todoListsArray.length; j++ ) {
				var n = todoListsArray[j]; // name
				var todos = todosArr[n];
				if ( todos != null && todos.length > 0) {		
					if ( subscriptions[n] == null ) { // ignore subscriptions					
						reminderFox_populateTodoToolTip(todos, (tooltipWrapLength - 13), n);	
					}
				}
			}	
	 	} 		
	}
 	
	var alarmsEnabled = true;
	var alertType;
	try {
		alertType = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ENABLE_ALERT_PREF);
	} 
	catch (e) {
		alertType = REMINDER_FOX_ENABLE_ALERT_PREF_ALL;
	}
	if (alertType.indexOf(REMINDER_FOX_SUSPEND_ALERT_PREF) != -1) {
		alarmsEnabled = false;
	}
	// if alarms are not enabled, we will keep to default status as an indicator that alarms are disabled
	if ( alarmsEnabled ) { 
		if ( todayRemindersArr.length > 0 ) {
			icon.setAttribute("status", "currentReminder");
		}
		else if ( upcomingRemindersArr.length > 0 ) {
			icon.setAttribute("status", "upcomingReminder");
		}	
	}	
	
}

function reminderFox_populateTodayToolTip(remindersArr, tooltipWrapLength) {
	var lblparent = document.getElementById("todaysRemindersBox");	
	// Get the template from the user preference	
	var template = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_TODAYS_REMINDERS_LABEL);
	reminderFox_populateToolTip(remindersArr, tooltipWrapLength, lblparent, template ) ;
}


function reminderFox_populateUpcomingToolTip( remindersArr, tooltipWrapLength) {
	var lblparent = document.getElementById("upcomingRemindersBox");
	// Get the template from the user preference	
	var template = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_UPCOMING_REMINDERS_LABEL);
	reminderFox_populateToolTip(remindersArr, tooltipWrapLength, lblparent, template ) ;
}

function reminderFox_populateToolTip(remindersArr, tooltipWrapLength, lblparent, template )  {
	var j;
	var remLabel;
	if (remindersArr.length > 0 ) {
		var lineWrappedIndent = 5;	
		for(var i=0; i < remindersArr.length; i++) {		
			var startIndex = 0;
			var completeRemainingString = reminderFox_populateReminderLabel(remindersArr[i], template, remindersArr[i].date);	
			var stringSeparatedByNewlines = completeRemainingString.split("\\n");
			for ( var z = 0; z < stringSeparatedByNewlines.length; z++ ) { 
				var remainingString = stringSeparatedByNewlines[z];
				var afterFirst = false;
				while ( remainingString.length > tooltipWrapLength  ) {				
					// go back to last whitespace
					var lastIndex = remainingString.lastIndexOf( ' ', tooltipWrapLength );
					var forceLineBreak = false;
					if ( lastIndex == -1 ) {
						forceLineBreak = true;
				    	lastIndex = tooltipWrapLength + 1;
					}
					if ( lastIndex != -1 ) {
					    var curStr = remainingString.substring( 0, lastIndex );
					    // after the first line, for any extra lines we will indent some.This makes
					    // the entry look nice when wrapping to the following lines
					    if ( afterFirst )  {
					    	j = 0;
					    	while ( j < lineWrappedIndent ) {
					    		curStr = " " + curStr;
					    		j++;
					    	}
					    }	
					    	    
					    remLabel = document.createElement("description");
						remLabel.setAttribute("value", curStr);
						if ( remindersArr[i].priority == REMINDER_PRIORITY_IMPORTANT) { 
							remLabel.setAttribute("style", "color: red;");
						}
						else {
							remLabel.removeAttribute( "style" );
						}
						lblparent.appendChild(remLabel);
						afterFirst = true;
					}
					
					if ( forceLineBreak ) {
						startIndex = lastIndex;
					}
					else {
						startIndex = lastIndex + 1;
					}
					remainingString = remainingString.substring( startIndex );		  										
				}
				if ( afterFirst )  {
				   	j = 0;
				   	while ( j < lineWrappedIndent ) {
				   		remainingString = " " + remainingString;
				   		j++;
				   	}
				}						
				reminderFox_addItemToTooltip( remindersArr[i], true, remainingString, lblparent );
			}
		}
	} else {
		var noneLabel = document.createElement("description");
		noneLabel.setAttribute("value",reminderFox_getBundle().getString( "rf.main.tooltip.reminders.none" ) );  
		lblparent.appendChild(noneLabel);
	}
}

function reminderFox_addItemToTooltip( reminderOrTodo, isReminder, labelText, parentElement ) {
	var hasNotes = reminderOrTodo.notes != null && reminderOrTodo.notes != "";
	var isRUC = false;
	var remLabel;
	if ( isReminder ) {
		isRUC = reminderOrTodo.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED;
	}
	if ( !hasNotes && !isRUC ) {   // no image needed
			remLabel = document.createElement("description");
			remLabel.setAttribute("value", labelText);
			if ( reminderOrTodo.priority == REMINDER_PRIORITY_IMPORTANT) { 
				remLabel.setAttribute("style", "color: red;");
			}
			else {
				remLabel.removeAttribute( "style" );
			}
			parentElement.appendChild(remLabel);
	}
	else {
			// create image box
			var hbox = document.createElement("hbox");			
			remLabel = document.createElement("description");
			var image1;
			var vbox = document.createElement("vbox");	
			var spacer = 	document.createElement("spacer");	
			spacer.setAttribute("flex", "1" )	
			vbox.appendChild( spacer );
			
			if ( ! (isRUC && hasNotes) ) {
				// if only 1 image  (remindUntilCompleted / notes )
				if ( hasNotes ) {
					image1 = document.createElement("image");
					image1.setAttribute("src", REMINDER_FOX_NOTES_IMAGE );
					vbox.appendChild( image1 );
				}
				else {
					image1 = document.createElement("image");
					image1.setAttribute("src", REMINDER_FOX_REMIND_UNTIL_COMPLETED_IMAGE );
					vbox.appendChild( image1 );
				}
			}
			else {				
				// if multi image
				var imagehbox = document.createElement("hbox");			
				image1 = document.createElement("image");
				image1.setAttribute("src", REMINDER_FOX_NOTES_IMAGE );
				imagehbox.appendChild( image1 );		
							
				var image2 = document.createElement("image");
				image2.setAttribute("src", REMINDER_FOX_REMIND_UNTIL_COMPLETED_IMAGE );
				imagehbox.appendChild( image2 );
				
				vbox.appendChild(imagehbox );
			}
			
			
			// end multi
			vbox.appendChild( spacer );

			remLabel.setAttribute("value", labelText);

			if ( reminderOrTodo.priority == REMINDER_PRIORITY_IMPORTANT) { 
				remLabel.setAttribute("style", "color: red;");
			}
			else {
				remLabel.removeAttribute( "style" );
			}
			hbox.appendChild( remLabel );
			hbox.appendChild( vbox );
			
			parentElement.appendChild(hbox);
	}
}


function reminderFox_populateTodoToolTip( todosArr, tooltipWrapLength, listName) {
	var containerVbox = document.getElementById("todosTooltip");
	
	var tooltipVbox = document.createElement("vbox");
	var todoDescription = document.createElement("description");
	todoDescription.setAttribute("id", "todoDescription");
	todoDescription.setAttribute("value", listName);
	todoDescription.setAttribute("style", "font-weight:bold;");
	tooltipVbox.appendChild(todoDescription);
	
	var todosBox = document.createElement("vbox");
	todosBox.setAttribute("id", "todosBox");
	tooltipVbox.appendChild(todosBox);				
	
	var spacer = document.createElement("spacer");
	spacer.setAttribute("height", "4px");
	tooltipVbox.appendChild(spacer);					
	
	containerVbox.appendChild(tooltipVbox);		
					
	var j;
	var remLabel;
	var template = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_UPCOMING_REMINDERS_LABEL);
	if (todosArr.length > 0 ) {
		for(var i=0; i < todosArr.length; i++) {	
			var lineWrappedIndent = 5;
			var startIndex = 0;
			var completeRemainingString = null;
			if ( todosArr[i].date != null ) {
				completeRemainingString = reminderFox_populateReminderLabel(todosArr[i], template, todosArr[i].date);	
			}
			else {
			     completeRemainingString = todosArr[i].summary;
			}			
			
			var stringSeparatedByNewlines = completeRemainingString.split("\\n");
			for ( var z = 0; z < stringSeparatedByNewlines.length; z++ ) { 
				var remainingString = stringSeparatedByNewlines[z];
				var afterFirst = false;
				while ( remainingString.length > tooltipWrapLength ) {				
					// go back to last whitespace
					var lastIndex = remainingString.lastIndexOf( ' ', tooltipWrapLength );
					var forceLineBreak = false;
					if ( lastIndex == -1 ) {
						forceLineBreak = true;
				    	lastIndex = tooltipWrapLength + 1;
					}					
					if ( lastIndex != -1 ) {
					    var curStr = remainingString.substring( 0, lastIndex );
					    // after the first line, for any extra lines we will indent some.  This makes
					    // the entry look nice when wrapping to the following lines
					    if ( afterFirst )  {
					    	j = 0;
					    	while ( j < lineWrappedIndent ) {
					    		curStr = " " + curStr;
					    		j++;
					    	}
					    }				    
					    
					    remLabel = document.createElement("description");
						remLabel.setAttribute("value", curStr);
						if ( todosArr[i].priority == REMINDER_PRIORITY_IMPORTANT ) {
							remLabel.setAttribute("style", "color: red;");
						}
						else {
						remLabel.removeAttribute( "style" );
						}
						todosBox.appendChild(remLabel);
						afterFirst = true;
					}
									
					if ( forceLineBreak ) {
						startIndex = lastIndex;
					}
					else {
						startIndex = lastIndex + 1;
					}
					remainingString = remainingString.substring( startIndex );				    										
				}
				if ( afterFirst )  {
				   	j = 0;
				   	while ( j < lineWrappedIndent ) {
				   		remainingString = " " + remainingString;
				   		j++;
				   	}
				}
				reminderFox_addItemToTooltip( todosArr[i], false, remainingString, todosBox );
			}
		}
	} else {
		var noneLabel = document.createElement("description");
		noneLabel.setAttribute("value", reminderFox_getBundle().getString( "rf.main.tooltip.reminders.none" ) );  
		todosBox.appendChild(noneLabel);
	}
}


function reminderFox_getTodaysAndUpcomingReminders() {
	var i, j, x;
	var reminder, todayReminder, upcomingReminder, allReminders;
	var endIndex, index;
	var reminderEvents = 	reminderFox_getReminderEvents();
	var todaysReminders = new Array();
	var upcomingReminders = new Array();

	var upcomingReminderDays =reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_UPCOMING_REMINDER_DAYS_PREF);
	if ( upcomingReminderDays > 364 ) {
		upcomingReminderDays = 364;
	}
	var todaysDate = new Date();
	var REPEAT_UPCOMING_OCCURRENCES;
	try {
		REPEAT_UPCOMING_OCCURRENCES =  reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_REPEAT_UPCOMING_OCCURRENCES);
	} catch(e) {
		 REPEAT_UPCOMING_OCCURRENCES = -1;
	}		

	var endDate  = new Date( todaysDate.getFullYear(), todaysDate.getMonth(), todaysDate.getDate() );
	endDate.setDate( endDate.getDate() + upcomingReminderDays );
	for( i = 0; i < reminderEvents.length; i++) {
		todayReminder = null;
		reminder = reminderEvents[i];
		
		// handle reminders marked Remind Until Complete as today reminders
		if ( reminder.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED ) {
	 		todayReminder = reminderFox_cloneReminderFoxEvent( reminder );	 		
			todayReminder.date  = new Date( todaysDate.getFullYear(), todaysDate.getMonth(), todaysDate.getDate(), 
					 			todayReminder.date.getHours(), todayReminder.date.getMinutes() );			
					 			
			if ( !reminderFox_isCompletedForDate( todayReminder, todayReminder.date ) ) {	
				todayReminder  = reminderFox_processReminderDescription(todayReminder, todayReminder.date.getFullYear(), false);	
				index = reminderFox_getSortNewUpcomingReminderIndex( todaysReminders, todayReminder );	
				reminderFox_insertIntoArray( todaysReminders, todayReminder, index );			
			}					 								
	 	}		
		
		
		// for performance reasons, sort all the yearly items first, which should generally be in order; then do the repeating ones afterwards,
		// as they will need to be inserted all over the arrays
		if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY || 
				reminder.recurrence.type  == REMINDER_RECURRENCE_ONETIME ) {
			allReminders = reminderFox_getAllRemindersInDateRange( reminder,  todaysDate, endDate, true );
			endIndex = 0;
			if ( allReminders.length > 0 ) {
				endIndex  = allReminders.length;
			}
			
			// have to have a check for -1 --> show all occurrences			
			if ( allReminders.length > 0) {
				 if ( !(allReminders.length == 1  &&  REPEAT_UPCOMING_OCCURRENCES >=1 ) )  {			
					for ( x = 0; x < allReminders.length; x++ ) {
						if ( reminderFox_compareDates( allReminders[x].date, todaysDate) != -1 ) {
							break;
						}
					}
					if ( REPEAT_UPCOMING_OCCURRENCES == -1 ) {
						endIndex = allReminders.length;
					}
					else {
						endIndex = x + REPEAT_UPCOMING_OCCURRENCES;
						if ( endIndex > allReminders.length ) {
							endIndex = allReminders.length;
						}
					}
				 }
			}
			
		    for (  j = 0; j < endIndex; j++ ) {					
				upcomingReminder = allReminders[j];
				
				if ( j == 0 ) { // special checking for first reminder
					if ( reminderFox_isCompletedForDate( upcomingReminder, upcomingReminder.date )  ) {
						continue;  //ignore first complete
					}
					
					// if it's marked as RUC and the date is not in the future, than we've already handled this as Today; skip it
					if (upcomingReminder.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED  ) {
						if ( reminderFox_compareDates(  upcomingReminder.date, todaysDate ) != 1 ) {
							continue;						
						}
					}
					else {
						// handle today's reminders
						if (reminderFox_compareDates(  upcomingReminder.date, todaysDate ) == 0 ) {
							todayReminder = reminderFox_cloneReminderFoxEvent( upcomingReminder );
							todayReminder  = reminderFox_processReminderDescription(todayReminder, todayReminder.date.getFullYear(), false);
							index = reminderFox_getSortNewUpcomingReminderIndex( todaysReminders, todayReminder );	
							reminderFox_insertIntoArray( todaysReminders, todayReminder, index );			
							continue;	
						}   	
					}
				}

				upcomingReminder  = reminderFox_processReminderDescription(upcomingReminder, upcomingReminder.date.getFullYear(), false);			
				index = reminderFox_getSortNewUpcomingReminderIndex( upcomingReminders, upcomingReminder );	
				reminderFox_insertIntoArray( upcomingReminders, upcomingReminder, index );
			}
		}
	}
	
	// now sort repeating items...
	for( i = 0; i < reminderEvents.length; i++) {
		todayReminder = null;
		reminder = reminderEvents[i];
		if ( reminder.recurrence.type  != REMINDER_RECURRENCE_YEARLY &&
				reminder.recurrence.type  != REMINDER_RECURRENCE_ONETIME ) {
			allReminders = reminderFox_getAllRemindersInDateRange( reminder,  todaysDate, endDate, true );
			// do the filtering here...
			endIndex = 0;
			if ( allReminders.length > 0 ) {
				endIndex  = allReminders.length;
			}
			
			// have to have a check for -1 --> show all occurrences			
			if ( allReminders.length > 0) {
				 if ( !(allReminders.length == 1  &&  REPEAT_UPCOMING_OCCURRENCES >=1 ) )  {			
					for ( x = 0; x < allReminders.length; x++ ) {
						if ( reminderFox_compareDates( allReminders[x].date, todaysDate) != -1 ) {
							break;
						}
					}
					if ( REPEAT_UPCOMING_OCCURRENCES == -1 ) {
						endIndex = allReminders.length;
					}
					else {
						endIndex = x + REPEAT_UPCOMING_OCCURRENCES;
						if ( endIndex > allReminders.length ) {
							endIndex = allReminders.length;
						}
					}
				 }
			}						
												
		   for (  j = 0; j < endIndex; j++ ) {	
				upcomingReminder = allReminders[j];
				
				if ( j == 0 ) { // special checking for first reminder
					if ( reminderFox_isCompletedForDate( upcomingReminder, upcomingReminder.date )  ) {
						continue;  //ignore first complete
					}
					
					// if it's marked as RUC and the date is not in the future, than we've already handled this as Today; skip it
					if (upcomingReminder.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED  ) {
						if ( reminderFox_compareDates(  upcomingReminder.date, todaysDate ) != 1 ) {
							continue;						
						}
					}
					else {
						// handle today's reminders
						if (reminderFox_compareDates(  upcomingReminder.date, todaysDate ) == 0 ) {
							todayReminder = reminderFox_cloneReminderFoxEvent( upcomingReminder );
							todayReminder  = reminderFox_processReminderDescription(todayReminder, todayReminder.date.getFullYear(), false);
							index = reminderFox_getSortNewUpcomingReminderIndex( todaysReminders, todayReminder );	
							reminderFox_insertIntoArray( todaysReminders, todayReminder, index );						
							continue;	
						}   	
					}
				}
				
				// add upcoming reminder
				upcomingReminder  = reminderFox_processReminderDescription(upcomingReminder, upcomingReminder.date.getFullYear(), false);			
					
				index = reminderFox_getSortNewUpcomingReminderIndex( upcomingReminders, upcomingReminder );	
				reminderFox_insertIntoArray( upcomingReminders, upcomingReminder, index );
			}
		}
	}

	return  { today: todaysReminders, upcoming: upcomingReminders  };	 	
}


function reminderFox_getVisibleTodos() {
	var todosArr = reminderFox_getReminderTodos();  //  iterate over  ALL  todos	
	var visibleTodosHashMap = { };
	var sortMap;
	
	var upcomingReminderDays =reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_UPCOMING_REMINDER_DAYS_PREF);
	if ( upcomingReminderDays > 364 ) {
		upcomingReminderDays = 364;
	}
	var endDate  = new Date(  );
	endDate.setDate( endDate.getDate() + upcomingReminderDays );	
	var todaysDate = new Date();
	for ( var n in todosArr ) {
		var todos = todosArr[n];

		if ( todos != null ) {
			 if ( visibleTodosHashMap[n] == null ) {
				visibleTodosHashMap[n] = new Array();
			}
			if ( sortMap == null ) {
				sortMap = new Array();
				var sortColumnsStr = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_SORT_COLUMNS_PREF);
			 	if ( sortColumnsStr != null && sortColumnsStr != ""  ) {
			 		var sortColumnsStrArray = sortColumnsStr.split(",");
			 		for ( var i = 0; i < sortColumnsStrArray.length; i++ ) { 
						var listName =  sortColumnsStrArray[i];
						i++;
						var sortCol = sortColumnsStrArray[i];
						i++;
						var sortDir = parseInt( sortColumnsStrArray[i] );
						sortMap[listName] = { sortColumn: sortCol, sortDirection:  sortDir };					
			 		}
			 	}
			}
			var currentTodosList  = visibleTodosHashMap[n];		
		    for(var  i = 0; i < todos.length; i++) {
		    	// only show if the todo has not been completed and the user wants to show it in the tooltip
				 if ( !todos[i].showInTooltip || reminderFox_isCompletedForDate(todos[i], todos[i].date) ) { 
					continue;
				}		
				else 	if ( todos[i].date != null && reminderFox_compareDates( todos[i].date, endDate ) == 1)  {
					// only show if the date is less than the user's Number of Upcoming Days
					 continue;			
				 }					 					 					
						
				var validTodo  = reminderFox_processReminderDescription(todos[i], todaysDate.getFullYear(), true);								
				currentTodosList[currentTodosList.length] =validTodo;
			}
			
		
			if ( sortMap[n] != null ) {
				
				var sortedArray = new Array(currentTodosList.length );
				for ( var i = 0; i < currentTodosList.length; i++ ) {
					sortedArray[i] = currentTodosList[i];
					sortedArray[i].originalIndex = i;
				}								
				reminderFox_quick_sort( sortedArray, sortMap[n].sortColumn, sortMap[n].sortDirection );
				visibleTodosHashMap[n] = sortedArray;
			}
		}
	}	 	
	
	return visibleTodosHashMap;
}


function reminderFox_storeTimeOfLastUpdate() {
	// output the last time of update for debugging, but only if the
	// preference already exists
	try {		
		reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LAST_UPDATE);

		var currentDate = new Date();
		var hours = currentDate.getHours();
		var mins = currentDate.getMinutes();
		var secs = currentDate.getSeconds();
		
		var readableMins = mins;
		if ( mins < 10 ) {
			readableMins = "0" + readableMins;
		}
		var readableSecs = secs;
		if ( secs < 10 ) {
			readableSecs = "0" + readableSecs;
		}
		reminderFox_prefsBranch.setCharPref(REMINDER_FOX_LAST_UPDATE, hours + ":" + readableMins + ":" + readableSecs);	
	} catch(e) {
		// pref doesn't exist.  Do nothing.
	}	
}


function reminderFox_moveBox() { 
	var toolbarPref = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_TOOLBAR);
	
    //check if box is ind the right location
    var toolbar = document.getElementById(toolbarPref);
    var box = document.getElementById("reminderFox-statusLabel");
    
    // if user has set to use no status bar, then hide it
	if ( toolbarPref == "none") { 
		box.setAttribute("hidden", "true");	
		return;
	}
	else {
		box.removeAttribute("hidden");	
	}

    var position;
    try {
    	position = reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_TOOLBAR_POSITION) ;
    }
    catch( e ) {
    	position = -1;
    }


    //if toolbar doesn't exist move to default location
    if (!toolbar) {
    	reminderFox_prefsBranch.setIntPref(REMINDER_FOX_TOOLBAR_POSITION, REMINDER_FOX_TOOLBAR_DEFAULT);
		reminderFox_prefsBranch.setIntPref(REMINDER_FOX_TOOLBAR_POSITION, REMINDER_FOX_TOOLBAR_POSITION_DEFAULT);      
     	return;
    }

    // bail if it is in the right place
    if (reminderFox_indexOf(toolbar,box, false) == position) {
	     return;
     }

    //remove us from parent
    box.parentNode.removeChild(box);
    
    reminderFox_insertAtIndex(toolbar, box, position);
	
	// add a check to make sure it's there...
	var found = false;
	var children = toolbar.childNodes;
	for ( var i = 0; i < children.length; i++ ) { 
		if ( children[i] == box ) { 
			found = true;
			break;
		}
	}
	if ( !found ) { // if it's not found, add it to the default status bar
		 var toolbar = document.getElementById("status-bar");
		 if ( box == null ) {
		 	box = document.getElementById("reminderFox-statusLabel");
		 }
		 if ( toolbar != null && box != null ) { 
			 toolbar.appendChild(box);
		}
	}
  }
  

 function reminderFox_insertAtIndex(aParent, aChild, aIndex)  {
    var children = aParent.childNodes;
    if ((children.length == 0) || (aIndex >= children.length) || (aIndex < 0)) {
      aParent.appendChild(aChild);
     }
    else {
       aParent.insertBefore(aChild, children[aIndex]);
     }
  }

function reminderFox_storeTimeOfLastAlert() {
	// output the last time of update for debugging, but only if the
	// preference already exists
	try {		
		var currentDate = new Date();		
		var time = currentDate.getTime();
		reminderFox_prefsBranch.setCharPref( REMINDER_FOX_LAST_ALERT, time);			
	} catch(e) {
		// pref doesn't exist.  Do nothing.
	}	
}

function reminderFox_storeTimeOfLastProcessed() {
	// output the last time of update for debugging, but only if the
	// preference already exists
	try {		
		var currentDate = new Date();		
		var time = currentDate.getTime();
		reminderFox_prefsBranch.setCharPref( REMINDER_FOX_LAST_PROCESSED, time);			
	} catch(e) {
		// pref doesn't exist.  Do nothing.
	}	
}

function reminderFox_updateForRemoteChange( statustxtString, actionID) {
	if ( actionID == 1 ||  // completed successfully (remote and local are equal, or were uploaded)
		actionID == 2  || // reminders were downloaded,  need to refresh reminders
		actionID == -1  // connection error - in this case we still need to proces reminders in case enough time has elapsed
	   ) {  
		var changed = reminderFox_processRecentReminders(); 	
		if ( changed ) {
			// write stuff out
			reminderFox_writeOutRemindersAndTodos(false);								
			reminderFox_syncWrittenChangesToRemote();		
		}
		
		var windowEnumerator =  reminderFox_getWindowEnumerator();
		if (windowEnumerator.hasMoreElements()) {
			var oldestWindow = windowEnumerator.getNext();		
			oldestWindow.reminderFox_updateRemindersInWindow();	
	
			oldestWindow.reminderFox_clearRemindersAndTodos();
			while (windowEnumerator.hasMoreElements()) {
				var currentWindow = windowEnumerator.getNext();		
				currentWindow.reminderFox_updateRemindersInWindow();		
				currentWindow.reminderFox_clearRemindersAndTodos();						
			}
		}
	}
}	

function reminderFox_ensureRemoteRemindersSynchronized( headless ) {  

	var waitForResponse = false;
	
	// sync 'em up 
	var networkSync = REMINDER_FOX_NETWORK_SYNCHRONIZE_DEFAULT;		
	try {
		networkSync = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_NETWORK_SYNCHRONIZE);
	} catch(e) {
	}	
	if ( networkSync ) {
		if ( headless ) {
			waitForResponse = true;
			reminderFox_download_Startup_headless(REMINDER_FOX_UI_MODE_HEADLESS_SHOW_ERRORS, reminderFox_updateForRemoteChange);
		}
		else {
			reminderFox_downloadReminders();
		}
	}		
	 
	return waitForResponse;
}

// this runs every hour and updates all of the windows with the latest reminders
function reminderFox_initializeReminderFox(clearReminders) {
	var windowEnumerator =  reminderFox_getWindowEnumerator();
	var currentDate;
	if (windowEnumerator.hasMoreElements()) {
		var oldestWindow = windowEnumerator.getNext();
		// if this is the very first (oldest) window opened, then let's process the reminders
		if ( window == oldestWindow ) {
			// verify that the correct amount of time has elapsed since last update.   Sometimes due to 
			// what appears to be a FireFox bug, sometimes a large number of  timeouts are called.  This
			// ensures that we only process once after the proper amount of time
			var lastTime = 		reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." +  REMINDER_FOX_LAST_PROCESSED);
			if ( !reminderFox_initialized  ) { 
				// the very first time, clear out the last time so that we always run when you start Firefox
				lastTime = "";
				reminderFox_initialized = true;
			}
			currentDate = new Date();
			var currentTime = currentDate.getTime();
			var lastTimeElapsed = null;
			if ( lastTime != null && lastTime != "" )  {
				lastTimeElapsed = parseInt(lastTime) + reminderFox_HOUR_TIMEOUT;
			}
			reminderFox_logMessageLevel(currentDate + "check - should Initialize: " + (lastTime == null  || lastTime == "" ||  (currentTime+500) >= lastTimeElapsed ) +  " ==  lastTime " + lastTime + " -- currentTime: " + currentTime + " -- lastTimeElapsed: " + lastTimeElapsed  + " - Difference (currentTime+500) - lastTimeElapsed:" + ((currentTime+500) -lastTimeElapsed) , REMINDER_FOX_LOG_LEVEL_FINE);
			if (lastTime == null  || lastTime == "" ||  (currentTime+500) >= lastTimeElapsed ) {	
				var updateWindows = false;
				var fileChanged = reminderFox_timeStampHasChanged();
				if ( fileChanged != -1 ) { 
					reminderFox_storeTimeStamp(fileChanged);					
				}

				var waitForResponse = reminderFox_ensureRemoteRemindersSynchronized(true);
				
				reminderFox_logMessageLevel( "network: waitForResponse:  " + waitForResponse   , REMINDER_FOX_LOG_LEVEL_SUPER_FINE);  //TODO
				
				var changed = false;
				try { 
					if ( !waitForResponse ) {
						changed = reminderFox_processRecentReminders(true);
					}
				}
				catch ( e ) {
				}
				if ( changed ) {
					updateWindows = true;
					// write stuff out
					reminderFox_writeOutRemindersAndTodos(false);								
					reminderFox_syncWrittenChangesToRemote();			
				}
			
				if ( fileChanged ) {
					updateWindows = true;
				}					
				currentDate = new Date();
				var day = currentDate.getDate();
				if ( reminderFox_lastDay  != day ) {
					updateWindows = true;
				}
				reminderFox_logMessageLevel("Initialize: " + currentDate + " --Update?: " + updateWindows +" -- fileChanged: " + fileChanged + ",  changed: " + changed + ", dayChanged: " + (reminderFox_lastDay != day), REMINDER_FOX_LOG_LEVEL_INFO);
				if ( updateWindows ) {
					oldestWindow.reminderFox_updateRemindersInWindow();	
					if ( clearReminders ) {
						// clear reminders from memory
						reminderFox_clearRemindersAndTodos();
					}	
					while (windowEnumerator.hasMoreElements()) {
						var currentWindow = windowEnumerator.getNext();		
						currentWindow.reminderFox_updateRemindersInWindow();		
						if ( clearReminders ) {
							// clear reminders from memory
							currentWindow.reminderFox_clearRemindersAndTodos();
						}							
					}
				}

				
				if ( clearReminders ) {
					// clear reminders from memory
					reminderFox_clearRemindersAndTodos();
				}			
				reminderFox_lastDay  = day;	
				reminderFox_logMessageLevel(currentDate + ": Setting Hourly timeout!", REMINDER_FOX_LOG_LEVEL_FINE);
				reminderFox_storeTimeOfLastProcessed();
		
				window.setTimeout(reminderFox_initializeReminderFoxHourly, reminderFox_HOUR_TIMEOUT);  // 10000 == 10 sec min
			}		
		}
	}
}


// this runs every hour and updates all of the windows with the latest reminders
function reminderFox_initializeReminderFoxHourly() {
	reminderFox_initializeReminderFox(true);
}

function reminderFox_updateRemindersInWindow() {
	reminderFox_logMessageLevel("Updating reminders in window: " + new Date(), REMINDER_FOX_LOG_LEVEL_INFO);	 
	
	var text = document.getElementById('reminderFox-statusLabel');
	if (text != null) {
		var reminderString = "";
		
		var todaysAndUpcomingReminders = reminderFox_getTodaysAndUpcomingReminders();
		var remindersArray =todaysAndUpcomingReminders.today;
		var important = false;
		for ( var i = 0; i < remindersArray.length; i++ ) {
			reminderString = reminderString + remindersArray[i].summary;
			if ( i < remindersArray.length - 1 ) {  
				reminderString = reminderString + ", ";
			}				
			if ( remindersArray[i].priority == REMINDER_PRIORITY_IMPORTANT ) {
				important = true;
			}
		}
		if (reminderString != "") { 
			
		  // get preference for how many chars to make this
		  var statusTextMaxLen =	40;
		  try {
				statusTextMaxLen = reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." +  REMINDER_FOX_STATUS_TEXT_MAX_LENGTH);	
			}
			catch ( e) {
			}
			
			// don't want text on status bar too long; truncate it after it gets big
			if ( reminderString.length > statusTextMaxLen ) {
				reminderString = reminderString.substring( 0, statusTextMaxLen ) + "...";
			}					
			
			var alarmsEnabled = true;
			var alertType;
			try {
				alertType = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ENABLE_ALERT_PREF);
			} 
			catch (e) {
				alertType = REMINDER_FOX_ENABLE_ALERT_PREF_ALL;
			}
			if (alertType.indexOf(REMINDER_FOX_SUSPEND_ALERT_PREF) != -1) {
				alarmsEnabled = false;
			}
			// if alarms are not enabled, we will keep to default status as an indicator that alarms are disabled
			if (alarmsEnabled) {
				if (important) {
					text.setAttribute("style", "color: red;");
				}
				else {
					text.removeAttribute("style");
				}
			}
			else {
				text.setAttribute("style", "color: grey;  text-decoration: line-through;");
			}

			var showStatusText = true;
			try {
				showStatusText = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_SHOW_STATUS_TEXT);
			} catch(e) {
			}
			if ( showStatusText ) {
				text.setAttribute("class", "statusbarpanel-iconic-text");
				text.setAttribute("label", reminderString);					
			}
			else {
				// user doesn't want the reminder text - just use icon
				text.setAttribute("class", "statusbarpanel-iconic");
			}					
		} else {
			text.setAttribute("class", "statusbarpanel-iconic");
		}

		reminderFox_createToolTip(remindersArray, todaysAndUpcomingReminders.upcoming);		
	}
}

function reminderFox_quickAlarmTooltip() {
	var quickAlarmTooltipBox = document.getElementById("quickAlarmTooltipBox");
	if ( quickAlarmTooltipBox != null ) {
	     while (quickAlarmTooltipBox.hasChildNodes()) {
	    	 quickAlarmTooltipBox.removeChild(quickAlarmTooltipBox.firstChild);
	  	 }		
	}

	var currentAlarms = reminderFox_getQuickAlarms();
	// sort array
	reminderFox_quick_sort_QuickArray( currentAlarms, 0 );
		
	if ( currentAlarms != null ) {

		for ( var i = 0; i < currentAlarms.length; i++ )  {
			var currentAlarm = currentAlarms[i];
			var text = currentAlarm.text;
			var snoozeTime = currentAlarm.snoozeTime;
			var alarmTime = currentAlarm.alarmTime;
			
			var currentTime = new Date().getTime();
			var actualAlarmTime = parseInt( snoozeTime ) - currentTime;
					
			var newDate = new Date( parseInt( alarmTime ) );
					
			var todaysDate = new Date();
			var dateVar = null;
			if ( newDate.getMonth() != todaysDate.getMonth() || newDate.getDate() != todaysDate.getDate() ) {
				var dateVariableString;
				try {
					dateVariableString = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LIST_DATE_LABEL);
				} catch(e) {
				}			
				var dateString =reminderFox_getDateVariable( null, newDate, dateVariableString );	
				dateVar = dateString + ", " + 	reminderFox_mail_getTimeString( newDate );
			}
			else {
				 dateVar = reminderFox_mail_getTimeString( newDate );
			}
			
			var remLabel = document.createElement("description");
			remLabel.setAttribute("value", text + " (" + dateVar + ")" );
			quickAlarmTooltipBox.appendChild(remLabel);
		}
	}
}


function reminderFox_activateOptionsContext(event) {	
	// dynamically handle the Show Alerts menu item 
	var alertType;
	try {
		alertType = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ENABLE_ALERT_PREF);
	} catch(e) {
		alertType = REMINDER_FOX_ENABLE_ALERT_PREF_ALL;
	}
			
	var suspendAlerts = document.getElementById("options-contextmenu-suspendAlerts");	
	if ( suspendAlerts != null ) { 
		// if the user has set it to no alerts, the option should be disabled
	//	if ( alertType == REMINDER_FOX_ENABLE_ALERT_PREF_NONE ) {
	//		suspendAlerts.setAttribute("disabled", "true");
	//		suspendAlerts.setAttribute("checked", "false");	    
	//	}
		// if alerts are suspended, the option is unchecked
		if ( alertType.indexOf( REMINDER_FOX_SUSPEND_ALERT_PREF ) != -1 ) {
			suspendAlerts.setAttribute("disabled", "false");
			suspendAlerts.setAttribute("checked", "true");
			
		}
		// otherwise, in normal case the option is checked
		else {
			suspendAlerts.setAttribute("disabled", "false");
			suspendAlerts.setAttribute("checked", "false");
		}	
	}
	
	// check if any current quick alarms, and show/hide the menu item list as appropriate
	var currentAlarms = reminderFox_getQuickAlarms();
	// sort array
	reminderFox_quick_sort_QuickArray( currentAlarms, 0 );
	
	var quickAlarmsList = document.getElementById("options-contextmenu-quickAlarms-list");		
	if (currentAlarms == null || currentAlarms.length == 0) {
		quickAlarmsList.setAttribute("hidden", "true");	
	}
	else {
		quickAlarmsList.removeAttribute( "hidden");	
		
		// show current lists...
		var moveToList = document.getElementById("options-contextmenu-quickAlarms-list-popup");	
		while (moveToList.hasChildNodes()) {
			 moveToList.removeChild(moveToList.firstChild);
		}
		
		if ( currentAlarms != null ) {
	
			for ( var i = 0; i < currentAlarms.length; i++ )  {
				var currentAlarm = currentAlarms[i];
				var text = currentAlarm.text;
				var snoozeTime = currentAlarm.snoozeTime;
				var alarmTime = currentAlarm.alarmTime;
				
				var currentTime = new Date().getTime();
				var actualAlarmTime = parseInt( snoozeTime ) - currentTime;
						
				var newDate = new Date( parseInt( alarmTime ) );
						
				var todaysDate = new Date();
				var dateVar = null;
				if ( newDate.getMonth() != todaysDate.getMonth() || newDate.getDate() != todaysDate.getDate() ) {
					var dateVariableString;
					try {
						dateVariableString = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LIST_DATE_LABEL);
					} catch(e) {
					}			
					var dateString =reminderFox_getDateVariable( null, newDate, dateVariableString );	
					dateVar = dateString + ", " + 	reminderFox_mail_getTimeString( newDate );
				}
				else {
					 dateVar = reminderFox_mail_getTimeString( newDate );
				}
				
				// add new menu item
				var menuItem = document.createElement("menuitem");
				menuItem.setAttribute( "id", text );
				menuItem.setAttribute( "label", text + " (" + dateVar + ")" );
				menuItem.setAttribute( "oncommand", "reminderFox_promptRemoveQuickAlarm(event.target)");
				moveToList.appendChild(menuItem);

			}
		}	
	}
}

function reminderFox_promptRemoveQuickAlarm( target ) {
	var quickAlarmText =  target.getAttribute( "id" );
	
	var quickAlarmLabel =  target.getAttribute( "label" );
	
	var quickAlarm = reminderFox_getQuickAlarm(quickAlarmText);
	
	// get Notes text if available
	if ( quickAlarm.notes != null && quickAlarm.notes.length > 0 ) {
		// replace new line characters with actual newline
		var notesText = quickAlarm.notes.replace(new RegExp(/\\n/g),"\n");
		quickAlarmLabel += "\n\n" + notesText;
	}
	
	var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                    .getService(Components.interfaces.nsIPromptService);
	
	var flags=promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
			promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1;     
	var msg = quickAlarmLabel;
	var buttonPressed = promptService.confirmEx(window,  reminderFox_getBundle().getString( "rf.alarm.quickalarms.label" ) + " " + quickAlarmText,
	  	msg,  flags,  reminderFox_getBundle().getString( "rf.alarm.quickalarms.remove.label" ), 
		reminderFox_getBundle().getString( "rf.button.ok" ), null, null, {});		  
	  
	// cancel pressed
	if ( buttonPressed == 0 ) {	
		reminderFox_removeQuickAlarm( quickAlarmText );
	}	  
}

function reminderFox_toggleShowAlert() {
	var alertType;
	try {
		alertType = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ENABLE_ALERT_PREF);
	} catch(e) {
		alertType = REMINDER_FOX_ENABLE_ALERT_PREF_ALL;
	}
	
	// if it's marked as suspended, change to original value
	var suspendedIndex = alertType.indexOf( REMINDER_FOX_SUSPEND_ALERT_PREF ) ;		
	if ( suspendedIndex != -1 ) {
		alertType = alertType.substring( suspendedIndex + REMINDER_FOX_SUSPEND_ALERT_PREF.length );
	}
	// otherwise, suspend the alert
	else {
		alertType = REMINDER_FOX_SUSPEND_ALERT_PREF + alertType;
	}
	
	reminderFox_prefsBranch.setCharPref( REMINDER_FOX_ENABLE_ALERT_PREF, alertType);
	
	// call this to update the icon status
	reminderFox_updateRemindersInWindow();
}

function processKeyPressedOnReminderTree(event) {
	if (event.keyCode == 46)
		removeReminder();
}

function reminderFox_showAlertSlider() {
	var i;
	var remindersArray;
	var windowEnumerator =  reminderFox_getWindowEnumerator();

	if (windowEnumerator.hasMoreElements()) {
		var oldestWindow = windowEnumerator.getNext();
		// Only show the alert  for the oldest window (the first browser you opened).  
		// We don't want each new window to have its own timeout to respond to, because we only
		// need to show one alert for all browser windows
		if ( window == oldestWindow ) {
			// don't show if the user has showReminders deselected in tooltip...  in that case, there is no todayReminder label to copy for alert so it would fail
			var showReminders = true;			
			try {
				showReminders = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_SHOW_REMINDERS_IN_TOOLTIP);
			} catch(e) {
			}		
		
			// Reshow alert after ALERT_TIMEOUT minutes.  -- (note: options dialog - needs to clear out lastAlert pref when changed)
			var alert_timeout = reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ALERT_TIMEOUT_PREF);

			if ( showReminders && alert_timeout > 0 ) {
				// convert from minutes to milliseconds	
				alert_timeout = alert_timeout * 60000; 
				
				// verify that the correct amount of time has elapsed since last alert slider.   Sometimes due to 
				// what appears to be a FireFox bug, sometimes a large number of alert timeouts are called.  This
				// ensures that only the correct one will display the alert slider after the proper amount of time
				var lastTime = 	reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." +  REMINDER_FOX_LAST_ALERT);
				  
				var lastTimeElapsed = null;
				if ( lastTime != null && lastTime != "" )  {
					lastTimeElapsed = parseInt(lastTime) + alert_timeout;
				}
				var currentDate = new Date();
				var currentTime =currentDate.getTime();
				
				reminderFox_logMessageLevel("Show AlertSlider? " + ((currentTime+100) >= lastTimeElapsed) + "...  Last time: " + lastTime + " - lastTimeElapsed: " 
					+ lastTimeElapsed + " - currentTime: " + currentTime
					, REMINDER_FOX_LOG_LEVEL_INFO);
					
				if (lastTime == null ||  (currentTime+100) >= lastTimeElapsed ) {  // +100 as small buffer (sometimes times are slightly off)

					// problem with MAC and alertslider
					var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
					.getService(Components.interfaces.nsIXULAppInfo);
				
					if ("1.9" > appInfo.platformVersion) {		// Gecko check 
						var alertComponent = Components.classes["@mozilla.org/alerts-service;1"]
						if ( alertComponent != null ) {
						   var alerts = alertComponent.getService(Components.interfaces.nsIAlertsService);
						}   
					} 	else {
						// due to some error with OS/2 use the previous code (for Gecko 1.8)
						var alerts = Components.classes["@mozilla.org/alerts-service;1"].getService(Components.interfaces.nsIAlertsService);
					
					}					
//					var alerts = Components.classes["@mozilla.org/alerts-service;1"].getService(Components.interfaces.nsIAlertsService);
					var alertType;
					try {
						alertType = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ENABLE_ALERT_PREF);
					} catch(e) {
						alertType = REMINDER_FOX_ENABLE_ALERT_PREF_ALL;
					}
					
					if ( alertType == REMINDER_FOX_ENABLE_ALERT_PREF_NONE ) {
					    return;
					}
					reminderFox_ensureRemindersSynchronized();
					//var remoteChanged = reminderFox_ensureRemoteRemindersSynchronized(true);   // do we want  alarm sync too?
					
					// check for empty today/upcoming - if both empty then ignore - check if today equals none string; if so, then check if upcoming == none string 
					var lblparent = document.getElementById("todaysRemindersBox").cloneNode(true);	
					var lblparent2 = document.getElementById("upcomingRemindersBox").cloneNode(true);	
			
				    var children = null;
				    var children2 = null;
				    var todayPref = false;
				    var upcomingPref = false;
				    if ( alertType == REMINDER_FOX_ENABLE_ALERT_PREF_TODAY || alertType == REMINDER_FOX_ENABLE_ALERT_PREF_ALL ) {
						children = lblparent.childNodes;
						todayPref = true;
					}						
					if ( alertType ==REMINDER_FOX_ENABLE_ALERT_PREF_UPCOMING || alertType == REMINDER_FOX_ENABLE_ALERT_PREF_ALL ) {
						children2 = lblparent2.childNodes;
						upcomingPref = true;
					}	
					var noToday = ( children == null || children.length == 0 || (  children.length == 1 && children[0].getAttribute( "value" ) == reminderFox_getBundle().getString( "rf.main.tooltip.reminders.none" )  ) );
					var noUpcoming =  ( children2 == null || children2.length == 0 || (  children2.length == 1 && children2[0].getAttribute( "value" ) == reminderFox_getBundle().getString( "rf.main.tooltip.reminders.none" )  ) );
					var ignoreAlert = noToday && noUpcoming;
	 				if ( !ignoreAlert  ) {	
	 					if ( !todayPref ) {
	 						lblparent = null;
	 					}
	 					if ( !upcomingPref ) {
	 						lblparent2 = null;
	 					}
		   				var newOptions = { todaysreminders: lblparent, upcomingreminders: lblparent2,  alertTypeToShow: alertType };	 					
	 					window.openDialog("chrome://reminderfox/content/alerts/reminderalert.xul",			"alert:alert", "chrome,dialog=yes,titlebar=no,popup=yes", newOptions );
					}
					
					reminderFox_clearRemindersAndTodos();				
					reminderFox_logMessageLevel("AlertSlider: " + currentDate, REMINDER_FOX_LOG_LEVEL_INFO);
					reminderFox_storeTimeOfLastAlert();  
					window.setTimeout(reminderFox_showAlertSlider, alert_timeout);   
					
				}
			}					
		}
	}
	// add some extra checks in when showing alert slider; in case the setTimeout threads have been suspended, 
	// this will kick them off again if neccessary
	reminderFox_initializeReminderFoxHourly();
}


// Automatically save reminders to backup files on FireFox startup
// Files:
//    reminders.ics.bak1  <-- always write to this on startup
//    reminders.ics.bak2   <--- check this...  if exists and > 24 hours since bak1, copy bak2 to bak3 and copy bak1 to bak2
//    reminders.ics.bak3
function reminderFox_saveReminders() {
	try {
		// initialize backup files
		var file;
		var savefilePath;
		// check if user has specified a specific file path in their preferences
		try {	//gW_OSswitching	
			savefilePath = rmFx_getStoreFile4OS();
		}
		catch ( e) {
		}
		
		var baseFilePath;
		// if not, then use default location in profile
		if ( savefilePath == null || savefilePath == "" ) {
			 file = Components.classes["@mozilla.org/file/directory_service;1"]
	       		  .getService(Components.interfaces.nsIProperties)
	    	      .get("ProfD", Components.interfaces.nsIFile);
	
		      file.append( "reminderfox" );
		      file.append( "reminderfox.ics"  );			
			  baseFilePath = file.path;
		}
		else {
			baseFilePath = savefilePath;
		}	
	
		var filePath1 = baseFilePath + ".bak1";
		var filePath2 = baseFilePath + ".bak2";
		var filePath3 = baseFilePath + ".bak3";
		
		var origFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		origFile.initWithPath( baseFilePath );
		
		var file2 = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		file2.initWithPath( filePath2 );
		
		var file1 = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		file1.initWithPath( filePath1 );
	
		// only write backup file if it differs from current file
		if ( !file1.exists() || file1.lastModifiedTime != origFile.lastModifiedTime)	{	
			// no file2 - create it
			if ( !file2.exists() ) {
				// bak2 doesn't exist.  Let's just write out to it			
				var leafName = file2.leafName;							
				var parentDir = file2.parent;
				if ( file1.exists() ) {
					// copy bak1 to bak2			
					var parentDir = file2.parent;
					var leafName = file2.leafName;
					file1.copyTo( parentDir, leafName);			
				}				
			}			
			else if ( file1.exists() && file1.lastModifiedTime != file2.lastModifiedTime)	{	// and only write out if backup2  file is actually different than backup1		
				var timeDifference = file1.lastModifiedTime  - file2.lastModifiedTime;

				// only copy bak1 to bak2 if it is over a day old
				if ( timeDifference > REMINDER_FOX_ONE_DAY ) {	// greater than a day old; update 
					// copy bak2 to bak3
					var file3 = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
					file3.initWithPath( filePath3 );
					var leafName = file3.leafName;
					if ( file3.exists() ) {
						file3.remove( true );
					}				
					var parentDir = file2.parent;
					file2.copyTo( parentDir,leafName);
								
					// copy bak1 to bak2			
					var parentDir = file2.parent;
					var leafName = file2.leafName;
					if ( file2.exists() ) { 
						file2.remove( true );
					}
					file1.copyTo( parentDir, leafName);												
				}
			}

			// write out current state to bak1
			if ( file1.exists() )	 {
				file1.remove(true);
			}	
			var leafName = file1.leafName;							
			var parentDir = file1.parent;
			origFile.copyTo( parentDir,leafName);											
		}				
	}		
	catch ( e ) {
		reminderFox_logMessageLevel("Failed saving backup file: " + e.name + ": " + e.description + ": " + e.number + ": " + e.message, REMINDER_FOX_LOG_LEVEL_INFO);
	}
}

function reminderFox_processQuickAlarms(returnMissed) {
	var alarmInfos = new Array();
	
	var delay = 1;
	var quickAlarms = reminderFox_getQuickAlarms();
	for ( var i = 0; i < quickAlarms.length; i++ ) { 
		var alarmText = quickAlarms[i].text;
		var alarmTime = quickAlarms[i].alarmTime;
		var snoozeTime = quickAlarms[i].snoozeTime;
		var notesText = null;
		if ( quickAlarms[i].notes != null && quickAlarms[i].notes.length > 0 ) { 
			notesText = quickAlarms[i].notes;
		}
		
		var currentTime = new Date().getTime();
		var actualAlarmTime = parseInt( alarmTime ) - currentTime;
						
		var processed = false;
		if (returnMissed ) {
			if ( actualAlarmTime < 0 ) {
				var newAlarm = { 
						quickAlarmText : alarmText,
						quickAlarmNotes : notesText,
						alarmTabPanel: null,
						alarmRecentReminder: null,
						alarmSnoozeTime: snoozeTime,
						alarmListName: null,
						alarmTimeString: null,
						alarmIsReminder: false,
						alarmIsTodo: false,
						alarmAlarmMissed: false,
						synccallback: reminderFox_networkSynchronizeCallback,
						clearLabelCallback: reminderFox_clearMailLabelCallback,
						alarmCurrentAlarmId: null,
						reminderTime: null,
						reminderTimeDifference : null 
					};
					
					alarmInfos[alarmInfos.length] = newAlarm;
					processed = true;
			}
		}
		
		if ( !processed ) {
			if ( actualAlarmTime < 0 ) {
				actualAlarmTime = 0 + ( reminderFox_ALARM_DELAY * delay );
				delay++;
			}				
			 
			 
			 
			var windowEnumerator =  reminderFox_getWindowEnumerator();
			if (windowEnumerator.hasMoreElements()) {
				//alert( "IN HERE yo: " + alarmText  + " -- " + actualAlarmTime);
				var oldestWindow = windowEnumerator.getNext();
				
				//alert( "alarm 7!" );
				// dump: here's another place to check that it is not more than 24 days in the future
				if ( 	actualAlarmTime  > 3600000 ) {  
					//  if alarm greater than an hour; don't add it; just let hourly process do it
				 }
				 else { 
					oldestWindow.setTimeout(
						oldestWindow.reminderFox_showQuickAlarm, 
						actualAlarmTime, alarmText, snoozeTime , notesText );
	
					reminderFox_logMessageLevel(new Date() + ": Setting quickalarm for " + alarmText + " -- snoozeTime: " + snoozeTime + " -- actualAlarmTime: " + actualAlarmTime , REMINDER_FOX_LOG_LEVEL_FINE);
				 }
			}	
		}	
	
	}
	
	return alarmInfos;
}

function reminderFox_bindKeys() {
	var keyset = document.getElementById("reminderFox_keyset");
	var openRF = reminderFox_getPreferenceValue( REMINDER_FOX_KEY_SHORTCUT_OPEN );
	var addRF = reminderFox_getPreferenceValue( REMINDER_FOX_KEY_SHORTCUT_ADD);
	var valid = {
		accel: "accel",
		ctrl: "control",
		control: "control",
		shift: "shift",
		alt: "alt",
		meta: "meta"
	};
	
	if ( openRF != null && openRF.length > 0 ) {
		var value = openRF;
		var parts = value.split(/\s+/);
		var modifiers = [];
		var keychar = null;
		var keycode = null;
		for (var i = 0; i < parts.length; i++) {
			if (parts[i].toLowerCase() in valid)
				modifiers.push(parts[i].toLowerCase());
			else if (parts[i].length == 1)
				keychar = parts[i];
			else if ("DOM_VK_" + parts[i].toUpperCase() in Components.interfaces.nsIDOMKeyEvent)
				keycode = "VK_" + parts[i].toUpperCase();
		}
		if (keychar || keycode) {
			var element = document.createElement("key");
			element.setAttribute("id", "key_open_RF");
			element.setAttribute("oncommand", "reminderFox_openAddRemindersDialog(true);");
			if (keychar)
				element.setAttribute("key", keychar);
			else
				element.setAttribute("keycode", keycode);
			element.setAttribute("modifiers", modifiers.join(","));
			if ( keyset != null ) {
				keyset.appendChild(element);
			}
		}
	}
	
	if ( addRF != null && addRF.length > 0 ) {
		var value = addRF;
		var parts = value.split(/\s+/);
		var modifiers = [];
		var keychar = null;
		var keycode = null;
		for (var i = 0; i < parts.length; i++) {
			if (parts[i].toLowerCase() in valid)
				modifiers.push(parts[i].toLowerCase());
			else if (parts[i].length == 1)
				keychar = parts[i];
			else if ("DOM_VK_" + parts[i].toUpperCase() in Components.interfaces.nsIDOMKeyEvent)
				keycode = "VK_" + parts[i].toUpperCase();
		}
	
		if (keychar || keycode) {
			var element = document.createElement("key");
			element.setAttribute("id", "key_add_RF");
			element.setAttribute("oncommand", "reminderFox_quickAddReminder();");
			if (keychar)
				element.setAttribute("key", keychar);
			else
				element.setAttribute("keycode", keycode);
			element.setAttribute("modifiers", modifiers.join(","));
			if ( keyset != null ) { 
				keyset.appendChild(element);
			}  
		}
	}
}

function reminderFox_start(){
  // run this later and let the window load.  
  window.setTimeout(function() { reminderFox_start_postInit(); }, 100);  

}

function reminderFox_runDebug() { 
	reminderFox_logMessageLevel( "\n\n\n##### DEBUG REPORT " , REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
	var windowEnumerator = reminderFox_getWindowEnumerator();
	if (windowEnumerator.hasMoreElements()) {
		var oldestWindow = windowEnumerator.getNext();
		
		reminderFox_logMessageLevel( "Total alarmlist length = "+ oldestWindow.reminderFox_alarmList.length , REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
							
		for (var i = 0; i < oldestWindow.reminderFox_alarmList.length; i++) {
			var currentAlarm = oldestWindow.reminderFox_alarmList[i];
			var reminderOrTodo =	reminderFox_getRemindersById( currentAlarm.alarmId);
			reminderFox_logMessageLevel( i + ". " + currentAlarm.alarmId + "; timeOfAlarm = " + currentAlarm.timeOfAlarm  + 
			" ;snoozed = "  + currentAlarm.snoozed + "; reminder objecdt= " + reminderOrTodo, REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
		  	if ( reminderOrTodo == null ) {
				reminderOrTodo =	reminderFox_getSpecificTodoById( currentAlarm.alarmId);
		  	}	

		  	if ( reminderOrTodo != null ) { 
		  		reminderFox_logMessageLevel( "Reminder: " + reminderOrTodo.summary + " -- " + reminderOrTodo.date, REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
		  		var ackDate = new Date();
				ackDate.setTime( currentAlarm.timeOfAlarm );  // TODO check
				reminderFox_logMessageLevel( "alarm date: : " + ackDate + "\n***\n", REMINDER_FOX_LOG_LEVEL_DEBUG);  //TODO
		  	}
		}
	}
}
function reminderFox_start_postInit() { 
	// load the default preferences (only the very first time that reminderfox is started; not each new window)
	var windowEnumerator =  reminderFox_getWindowEnumerator();
	if (windowEnumerator.hasMoreElements()) {
		var oldestWindow = windowEnumerator.getNext();
		if ( window == oldestWindow ) {
			reminderFox_loadDefaultPreferences();  // only call the first time
			
			// do keybindings
			reminderFox_bindKeys();
			
			
		}
	}

	reminderFox_moveBox();
	
	rmFxMsg.whichMessenger();    // this sets the global parameters for
								 // Messenger and TB/AB3
	
	var menu = document.getElementById("contentAreaContextMenu");
	if ( menu != null ) { 		
  		menu.addEventListener("popupshowing", reminderFox_ContextMenuPopup, false);
	}

	// 2009-02-25  TB3.x  add for popupshowing handling
	 var msgContext = document.getElementById("mailContext");
	 if (msgContext != null)
	    msgContext.addEventListener("popupshowing", rmFxPopupCheck, false);
	
	//gW TB3 2008-05-05  add for popupshowing handling
	 var msgContext = document.getElementById("messagePaneContext");
	 if (msgContext != null)
	    msgContext.addEventListener("popupshowing", rmFxPopupCheck, false);
	
	 var thContext = document.getElementById("threadPaneContext");
	 if (thContext != null)
	    thContext.addEventListener("popupshowing", rmFxPopupCheck, false);
	
	 var attContext = document.getElementById("attachmentListContext");
	 if (attContext != null)
	    attContext.addEventListener("popupshowing", rmFxPopupCheck, false);

	//gW_PB 2009-06-18		add Postbox handling
	 var attContext = document.getElementById("dataPaneAttachmentContextMenu");
	 if (attContext != null)
	    attContext.addEventListener("popupshowing", rmFxPopupCheck, false);


	// if this is the very first window opened, then let's set the timeout on it.
	reminderFox_initializeReminderFox(false); 

	// Initialize reminder fox for the browser window
	var windowEnumerator =  reminderFox_getWindowEnumerator();
	if (windowEnumerator.hasMoreElements()) {
		var oldestWindow = windowEnumerator.getNext();
		if ( window != oldestWindow ) {
			//  it's just a new window, we'll load it (tooltips, status bar)
			reminderFox_updateRemindersInWindow();	
		}
		else {
			// if this is the very first window, save out the reminders to backup file(s)
			reminderFox_saveReminders();		
			
			// Show the alert slider when the reminders are first initialized.
			// Only show if this is the oldest window (the first browser you opened).  That is, 
			// if you open a new window, we do not need to show the alert again.  
			window.setTimeout(reminderFox_showAlertSlider, 10000);    // add a delay of 5 seconds to account for browser loading 
			
			//reminderFox_processQuickAlarms();						
		}
	}

	// clear reminders from memory
	reminderFox_clearRemindersAndTodos();
}

function reminderFox_getTimeString( reminder, date ) {
	var timeString = null;
	var reminderDate = date;
	if ( reminder != null && date == null ) { 
		reminderDate = reminder.date;
	}
	if (reminder == null || !reminder.allDayEvent ) {
		try {
			var hours = reminderDate.getHours();
			var AMorPM;
				
			var use24HourTime;
			try {
				use24HourTime = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_USE_24_HOUR_TIME);
			} catch(e) {
			}				
			if (  use24HourTime ) {
				AMorPM = "";
				if ( hours < 10 ) {
					hours = "0" + hours;
				}
			}
			else {
				AMorPM  =reminderFox_getBundle().getString("rf.add.time.PM");
				if ( AMorPM != "" ) {
					if ( hours < 12 ) {
						AMorPM = reminderFox_getBundle().getString("rf.add.time.AM");
					}
					if ( hours == 0 ) {
						hours = 12;
					}
					if ( hours >= 13 ) {
						hours = hours -12;
					}	
				}	
			}
		
			var minutes = reminderDate.getMinutes();
			if ( minutes < 10 ) {
				minutes = "0" + minutes;
			}
							
			timeString = hours + reminderFox_getBundle().getString("rf.add.time.delimiter") + minutes;
			if ( AMorPM != "" ) {
				timeString = timeString + " " + AMorPM;		
			}
		}
		catch ( e ) { 
		}
	}	
	return timeString;
}

function reminderFox_populateReminderLabel( reminder , template, date) {
	var reminderLabel = template;

	// Replace the [variables]	
	var startBracketIndex =reminderLabel.indexOf("[");
	while (startBracketIndex != -1) {
		var endBracketIndex = reminderLabel.indexOf("]", startBracketIndex);
		if (endBracketIndex != -1) {
			// Check for a fishy [
			if (endBracketIndex - startBracketIndex < 3) {
				startBracketIndex = reminderLabel.indexOf("[", ++startBracketIndex);
			}
			else {
				var variable = reminderLabel.substring(startBracketIndex + 1, endBracketIndex);			
				var decodedVariable = reminderFox_decodeReminderLabelVariable(reminder, variable, date);
				var decodedVariableLength = decodedVariable.length;
				var startTrim = startBracketIndex;
				var endTrim = endBracketIndex;
				if ( variable == "time" && decodedVariableLength == 0 ) {
					// trim the ( ) from around time if the time is empty (all-day event)
					if ( reminderLabel.charAt( startBracketIndex - 1 ) == "(" &&
						reminderLabel.charAt( endBracketIndex + 1 ) == ")"  ) {
						startTrim = startTrim - 1;
						endTrim = endTrim + 1;
					}
				}
				reminderLabel = reminderLabel.substring(0, startTrim) + decodedVariable + reminderLabel.substring(endTrim + 1, reminderLabel.length);
				startBracketIndex = reminderLabel.indexOf("[", startBracketIndex + decodedVariableLength);
			}
		}
		else {
			// no ending bracket....  break out.
			startBracketIndex = -1;
		}
	}
	return reminderLabel;
}

function reminderFox_getDaysUntilDate( targetDate ) {
	var currentDate = new Date();
	var date = new Date( targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate() );	
	date.setHours( 0, 0, 0 );
	currentDate.setHours( 0, 0, 0 );
	
    // The number of milliseconds in one day
    var ONE_DAY = 1000 * 60 * 60 * 24

    // Convert both dates to milliseconds
    var date1_ms = date.getTime()
    var date2_ms = currentDate.getTime()

    // Calculate the difference in milliseconds
    var difference_ms = Math.abs(date1_ms - date2_ms)
    
    // Convert back to days and return
    return Math.round(difference_ms/ONE_DAY)
}

function reminderFox_decodeReminderLabelVariable(reminder, variable, date) {
	var decodedVariable = "";

		//gW two-digit number !! 
		function dVal(val) { 
			if (val < 10) val = "0" + val;
			return val; 
		}
		
	switch (variable) {
		case "reminderDesc":
			decodedVariable = reminder.summary;
        	break;
      	case "longDay":
      		if ( date != null ) {
      			decodedVariable = reminderFox_integerToLongDay(date.getDay());
      		}
        	break;
		case "shortDay":
			if ( date != null ) {
				decodedVariable = reminderFox_integerToShortDay(date.getDay());
			}
        	break;            
		case "longMonth":
			if ( date != null ) {
				decodedVariable = reminderFox_integerToLongMonth(date.getMonth());
			}
        	break;
		case "shortMonth":
			if ( date != null ) {
				decodedVariable = reminderFox_integerToShortMonth(date.getMonth());
			}
        	break;
		case "numMonth":
			if ( date != null ) {
				decodedVariable = (date.getMonth() +1)  + "";
			}
        	break;
		case "numMonth2":
			if ( date != null ) {
				decodedVariable = dVal(date.getMonth() +1) + "";
			}
        	break;
		case "date":
			if ( date != null ) {
				decodedVariable = (date.getDate()) + "";
			}
        	break;            
		case "date2":
			if ( date != null ) {
				decodedVariable = dVal(date.getDate()) + "";
			}
        	break;            
		case "longYear":
			if ( date != null ) {
				decodedVariable = date.getFullYear() + "";
			}
        	break;
		case "shortYear":
			if ( date != null ) {
				var fullYear = date.getFullYear() + "";
				decodedVariable = fullYear.substring(2);
			}
        	break;
		case "time":
			if ( date != null ) {
				if ( reminder != null ) { 
					if (reminder.allDayEvent)
						decodedVariable = "";
					else
						decodedVariable = reminderFox_getTimeString(reminder, date);
				}
				else {
					decodedVariable = "";
				}
			}
	        break;            
		case "daysUntil":
			if ( date != null ) {
				decodedVariable = reminderFox_getDaysUntilDate( date );
			}
        	break;
		case "timeUntil":
            if ( date != null ) {
                decodedVariable = reminderFox_getTimeUntilDate( date, reminder );
            }        	
            break;
        case "category":
        	if ( reminder.categories != null ) {	       
        		decodedVariable = reminder.categories;
        	}
        	break;
   		case "location":
   			if ( reminder.location != null ) {
        		decodedVariable = reminder.location;
   			}
        	break;        	
        default:
        	decodedVariable = "[" + variable + "]";
        	break;
    } 
    return decodedVariable;
}

function reminderFox_getTimeUntilDate( targetDate, reminder  ) {
    var currentDate = new Date();
    var date = new Date( targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate(), targetDate.getHours(), targetDate.getMinutes() );

    var ONE_DAY = 1000 * 60 * 60 * 24

    // Convert both dates to milliseconds
    var date1_ms = date.getTime()
    var date2_ms = currentDate.getTime()

    // Calculate the difference in milliseconds
    var difference_ms =date1_ms - date2_ms;
    if ( difference_ms < 0 ) {
    	return "";  // this time has already passed
    }
    var days = (difference_ms/ONE_DAY)
    var returnval = "";

    if (days > 1)
       {
       	var daysUntil = reminderFox_getDaysUntilDate( targetDate );
       	if ( daysUntil == 1 ) {
       		return daysUntil + " " + reminderFox_getBundle().getString("rf.reminderoptions.notify.day.label");  
       	}
       	else {
       		return daysUntil + " " + reminderFox_getBundle().getString("rf.reminderoptions.notify.days.label");  
       	}
    }
    else {
    	// it's an all-day reminder.  Say '1 day' as smallest increment
    	if ( reminder != null && reminder.allDayEvent ) {
    		return "1" + " " + reminderFox_getBundle().getString("rf.reminderoptions.notify.day.label");  
    	}
    	
      //It's less than a day, try hours
      var ONE_HOUR = 1000 * 60 * 60
      var hours = (difference_ms/ONE_HOUR)
      if (hours > 1)
         {
         if (Math.round(hours) == 1)
            returnval = Math.round(hours) + " " + reminderFox_getBundle().getString("rf.reminderoptions.notify.hour.label");  
            else
            returnval = Math.round(hours) + " " + reminderFox_getBundle().getString("rf.reminderoptions.notify.hours.label");  
         }
      else {
          //It's less than an hour, showm minutes
 		   var ONE_MINUTE = 1000 * 60
           var minutes = (difference_ms/ONE_MINUTE);
           if (Math.round(minutes) == 1)
              returnval = Math.round(minutes) + " " + reminderFox_getBundle().getString("rf.reminderoptions.notify.minute.label");  
              else
              returnval = Math.round(minutes) + " " + reminderFox_getBundle().getString("rf.reminderoptions.notify.minutes.label");  
           }
    }
	return returnval
}


function reminderFox_integerToShortDay( dayOfWeek) {
	var shortDay = "";
	switch (dayOfWeek) {
		case 0:
			shortDay =  reminderFox_getBundle().getString("rf.options.day.0.name.Mmm");
        	break;
      	case 1:
      		shortDay = reminderFox_getBundle().getString("rf.options.day.1.name.Mmm");
        	break;
		case 2:
			shortDay =  reminderFox_getBundle().getString("rf.options.day.2.name.Mmm");
        	break;            
		case 3:
			shortDay =  reminderFox_getBundle().getString("rf.options.day.3.name.Mmm");
        	break;
		case 4:
			shortDay =  reminderFox_getBundle().getString("rf.options.day.4.name.Mmm");
        	break;
		case 5:
			shortDay =  reminderFox_getBundle().getString("rf.options.day.5.name.Mmm");
        	break;
		case 6:
			shortDay =  reminderFox_getBundle().getString("rf.options.day.6.name.Mmm");
        	break;            
    } 
    return shortDay;
}

function reminderFox_integerToLongDay( dayOfWeek) {
	var longDay = "";
	switch (dayOfWeek) {
		case 0:
			longDay =  reminderFox_getBundle().getString("rf.options.day.0.name");
        	break;
      	case 1:
      		longDay =  reminderFox_getBundle().getString("rf.options.day.1.name");
        	break;
		case 2:
			longDay =  reminderFox_getBundle().getString("rf.options.day.2.name");
        	break;            
		case 3:
			longDay =  reminderFox_getBundle().getString("rf.options.day.3.name");
        	break;
		case 4:
			longDay =  reminderFox_getBundle().getString("rf.options.day.4.name");
        	break;
		case 5:
			longDay =  reminderFox_getBundle().getString("rf.options.day.5.name");
        	break;
		case 6:
			longDay =  reminderFox_getBundle().getString("rf.options.day.6.name");
        	break;            
    } 
    return longDay;
}

function reminderFox_integerToLongMonth( monthOfYear ) {
	var longMonth = "";
	switch (monthOfYear) {
		case 0:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.0.name");
        	break;
      	case 1:
      		longMonth = reminderFox_getBundle().getString("rf.options.month.1.name");
        	break;
		case 2:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.2.name");
        	break;            
		case 3:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.3.name");
        	break;
		case 4:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.4.name");
        	break;
		case 5:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.5.name");
        	break;
		case 6:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.6.name");
        	break;
      	case 7:
      		longMonth =  reminderFox_getBundle().getString("rf.options.month.7.name");
        	break;
		case 8:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.8.name");
        	break;            
		case 9:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.9.name");
        	break;
		case 10:
			longMonth =  reminderFox_getBundle().getString("rf.options.month.10.name");
        	break;
		case 11:
			longMonth = reminderFox_getBundle().getString("rf.options.month.11.name");
        	break;          
    } 
    return longMonth;
}

function reminderFox_integerToShortMonth( monthOfYear ) {
	var shortMonth = "";
	switch (monthOfYear) {
		case 0:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.0.Mmm");
        	break;
      	case 1:
      		shortMonth = reminderFox_getBundle().getString("rf.options.month.1.Mmm");
        	break;
		case 2:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.2.Mmm");
        	break;            
		case 3:
			shortMonth = reminderFox_getBundle().getString("rf.options.month.3.Mmm");
        	break;
		case 4:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.4.Mmm");
        	break;
		case 5:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.5.Mmm");
        	break;
		case 6:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.6.Mmm");
        	break;
		case 7:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.7.Mmm");
        	break;
      	case 8:
      		shortMonth = reminderFox_getBundle().getString("rf.options.month.8.Mmm");
        	break;
		case 9:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.9.Mmm");
        	break;            
		case 10:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.10.Mmm");
        	break;
		case 11:
			shortMonth =  reminderFox_getBundle().getString("rf.options.month.11.Mmm");
        	break;         
    } 
    return shortMonth;
}

function reminderFox_addReminderForWebPage() {
	var textWindow = document.commandDispatcher.focusedWindow;
	var text = textWindow.getSelection();     
	var notes = null;
	if ( text != null ) {
		text = text.toString();		
		text =reminderFox_trim(text);
		if ( text.length > 0 ) {
			notes = text;
		}
	}
	
	var subject = content.document.title ;
	var url = content.location.href;
	
	var newDate = new Date();
	newDate.setDate( newDate.getDate() );  // default to using today's date for reminder

	var reminderId =reminderFox_generateUniqueReminderId( newDate );
	var	newReminderToBeAdded = new ReminderFoxEvent( reminderId, newDate, subject );
	//newReminderToBeAdded.messageID = remFoxMessageID;
	// newReminderToBeAdded.recurrence.type = REMINDER_RECURRENCE_ONETIME;
	newReminderToBeAdded.url = url;
	// add default message header info to the Notes section
	if ( notes != null ) {
		newReminderToBeAdded.notes = notes;
	}
	    
	reminderFox_addReminderHeadlessly( newReminderToBeAdded );
	
 
}

function reminderFox_quickAddReminder() { 
   var newReminderToBeAdded = null;
   var isTodo = false;     //gW_AddEvent via Clipboard  2010-08-27
   var clipboardData = rmFxUtil.copyTextfromClipboard();
   if (clipboardData != null) {
		if (clipboardData.indexOf("BEGIN:VEVENT") != -1 ||
		clipboardData.indexOf("BEGIN:VTODO") != -1) {
			var reminderEvents = new Array();
			var reminderTodosArr = new Array();
			
			reminderFox_readInRemindersAndTodosICSFromString(reminderEvents, reminderTodosArr, clipboardData, false /*ignoreExtraInfo*/);
			if (reminderEvents[0] != null) {
				newReminderToBeAdded = reminderEvents[0];
			}
			else {
				// get VTODO - the first only
				for (var list in reminderTodosArr) {
					newReminderToBeAdded = reminderTodosArr[list][0];
					isTodo = true;
					break;
				}
			}
		}
	}
	if (newReminderToBeAdded == null) {
		var newDate = new Date();
		var reminderId = reminderFox_generateUniqueReminderId(newDate);
		newReminderToBeAdded = new ReminderFoxEvent(reminderId, newDate, null);
		reminderFox_addReminderHeadlessly(newReminderToBeAdded);
	}
	else {
		// addding from clipboard
		reminderFox_addReminderHeadlessly(newReminderToBeAdded, true /*replaceEventIfAlreadyExists*/, true /*isEdit*/, isTodo);
	}
}

function reminderFox_ContextMenuPopup() {
	var addReminderMenuItem = document.getElementById("rf_addReminder");
	var subscribeReminderMenuItem = document.getElementById("rf_subscribeReminder");
	
	var contextMenusEnabled = true;			
	try {
		contextMenusEnabled = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ENABLE_CONTEXT_MENUS);
	} catch(e) {
	}			
	
	// user doesn't want context menus; hide them
	if (!contextMenusEnabled ) {
		addReminderMenuItem.hidden =true;
   		subscribeReminderMenuItem.hidden = true;
   		return;
	}
	
	addReminderMenuItem.hidden =false;
   	subscribeReminderMenuItem.hidden = false;
 	
	
	
	if (gContextMenu.onLink) {		
   		addReminderMenuItem.hidden =true;
   		subscribeReminderMenuItem.hidden = true;
   		
   		// show subscribe context item if a calendar-type link
		var currentLink =  gContextMenu.link.href;
		if ( currentLink != null ) {
			if ( currentLink.indexOf( "webcal") != -1 ||
				currentLink.indexOf( "ical") != -1 ||
				currentLink.indexOf( "ics") != -1 ) {				
				subscribeReminderMenuItem.hidden = false;
			}				
		}
	}
	else {		
		addReminderMenuItem.hidden =false;
		subscribeReminderMenuItem.hidden = true;
	}
}


function reminderFox_subscribeWithReminderFox(subscriptionUrl) {
//gW D&D 2008-04
	if (subscriptionUrl == null) {	   
	/*var*/ subscriptionUrl = gContextMenu.link.href;
	}
	// default name to the name of the ics file
	var name = null;
	var endIndex = subscriptionUrl.indexOf( ".ics" );
	if ( endIndex != -1 && endIndex == subscriptionUrl.length - ".ics".length ) {
		var slashIndex = subscriptionUrl.lastIndexOf( "/", endIndex );
		if ( slashIndex != -1 ) {
			name = subscriptionUrl.substring( slashIndex + 1, endIndex );
		}
	} 
	
	var callOptions = { added: false,  addEvent: 1,  currentItem: name, subscription: subscriptionUrl  };
	window.openDialog("chrome://reminderfox/content/options/addCustomList.xul",
		"reminderFox-editAdd-customList", "chrome,resizable,modal", callOptions );
	
	if ( callOptions.added == true ) {
		var added = false;
		// set new list name
		try { 
			var newListName = callOptions.currentItem;
			var todoLists = reminderFox_getPreferenceValue( REMINDER_FOX_TODO_LISTS );
	 		if ( todoLists != null && todoLists.length > 0) { 	 	
	 			todoLists = todoLists + "," + newListName;
	 		}
	 		else {
	 			todoLists = newListName;
	 		}		
			reminderFox_setUnicodePref( REMINDER_FOX_TODO_LISTS, todoLists);
			
			// add subscription
			var subscriptions = reminderFox_getSubscriptions();								
			if ( subscriptionUrl != null  ) {
				subscriptions[callOptions.currentItem] = callOptions.subscription; 
				reminderFox_writeSubscriptions( subscriptions );
				added = true;
			}		
			reminderFox_prefs.savePrefFile(null); 
		} catch ( e ) {			
		}   
		
		if ( added ) {
			alert( "ReminderFox: " + reminderFox_getBundle().getString("rf.options.customlist.subscribe.confirm.title") + " " + subscriptionUrl);;
		}										
		else {
			alert( "ReminderFox: " + reminderFox_getBundle().getString("rf.options.customlist.subscribe.failed.title") + " " + subscriptionUrl);;
		}
	}
}

function reminderFox_onclickFunc(event, element) {
	oeDatePicker.launchAdd = true;
	var treeContextMenu = document.getElementById("oe-date-picker-popup");
	treeContextMenu.showPopup(element, event.screenX, event.screenY, "bottomleft", "topleft"); 
}

function reminderfox_showCalendar(event) {
	var show = false;
	if ( event == null ) {
		show = true;
	}
	else {
		var target =  event.target.getAttribute( "id" );
		if ( target == "oe-date-picker-popup" ) {
			// if the target is not the popup (it could be a tooltip) we ignore it
			show = true;
		}

	}
	
	if ( show ) {
		oeDatePicker.resizeCalendar();  
		var reminderDate =  new Date();
		oeDatePicker.onpopupshowing(reminderDate, true, false, true);	
	}	
}

  	
// fmt Date/Time string with RmFx definition from 'Options' settings 

function	rmFx_getDatum() {
	var date = new Date();   
	
	var timeString = reminderFox_mail_getTimeString( date );
	var dateVariableString;
	try {
		dateVariableString = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + 
			"." + REMINDER_FOX_LIST_DATE_LABEL);
	} catch(e) { }
      
 	return  reminderFox_getDateVariable( null, date, dateVariableString )
            + " " + timeString;
}


/**
 * Dispatch functions using the JS Subscript Loader in order to delay loading of javascript
 * for specific usecases.
 */
function dispatch_reminderFox_addReminder4Contact(reminderOrCopy) {
	var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
	                       .getService(Components.interfaces.mozIJSSubScriptLoader);
	loader.loadSubScript("chrome://reminderfox/content/mail/addContact2Reminder.js");
	reminderFox_addReminder4Contact(reminderOrCopy);
}